Coverage for pySDC/core/hooks.py: 98%

54 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-20 14:51 +0000

1import logging 

2from collections import namedtuple 

3 

4 

5# metadata with defaults 

6meta_data = { 

7 'process': None, 

8 'process_sweeper': None, 

9 'time': None, 

10 'level': None, 

11 'iter': None, 

12 'sweep': None, 

13 'type': None, 

14 'num_restarts': None, 

15} 

16Entry = namedtuple('Entry', meta_data.keys()) 

17 

18 

19# noinspection PyUnusedLocal,PyShadowingBuiltins,PyShadowingNames 

20class Hooks(object): 

21 """ 

22 Hook class to contain the functions called during the controller runs (e.g. for calling user-routines) 

23 

24 When deriving a custom hook from this class make sure to always call the parent method using e.g. 

25 `super().post_step(step, level_number)`. Otherwise bugs may arise when using `filer_recomputed` from the stats 

26 helper for post processing. 

27 

28 Attributes: 

29 logger: logger instance for output 

30 __num_restarts (int): number of restarts of the current step 

31 __stats (dict): dictionary for gathering the statistics of a run 

32 entry (namedtuple): statistics entry containing all information to identify the value 

33 """ 

34 

35 entry = Entry 

36 meta_data = meta_data 

37 

38 def __init__(self): 

39 """ 

40 Initialization routine 

41 """ 

42 self.__num_restarts = 0 

43 

44 self.logger = logging.getLogger('hooks') 

45 

46 # create statistics and entry elements 

47 self.__stats = {} 

48 

49 def add_to_stats(self, value, **kwargs): 

50 """ 

51 Routine to add data to the statistics dict. Please supply the metadata as keyword arguments in accordance with 

52 the entry class. 

53 

54 Args: 

55 value: the actual data 

56 """ 

57 # create named tuple for the key and add to dict 

58 meta = { 

59 **self.meta_data, 

60 **kwargs, 

61 'num_restarts': self.__num_restarts, 

62 } 

63 self.__stats[self.entry(**meta)] = value 

64 

65 def increment_stats(self, value, initialize=None, **kwargs): 

66 """ 

67 Routine to increment data to the statistics dict. If the data is not yet created, it will be initialized to 

68 initialize if applicable and to value otherwise. Please supply metadata as keyword arguments in accordance with 

69 the entry class. 

70 

71 Args: 

72 value: the actual data 

73 initialize: if supplied and data does not exist already, this will be used over value 

74 """ 

75 meta = { 

76 **meta_data, 

77 **kwargs, 

78 'num_restarts': self.__num_restarts, 

79 } 

80 key = self.entry(**meta) 

81 if key in self.__stats.keys(): 

82 self.__stats[key] += value 

83 elif initialize is not None: 

84 self.__stats[key] = initialize 

85 else: 

86 self.__stats[key] = value 

87 

88 def return_stats(self): 

89 """ 

90 Getter for the stats 

91 

92 Returns: 

93 dict: stats 

94 """ 

95 return self.__stats 

96 

97 def reset_stats(self): 

98 """ 

99 Function to reset the stats for multiple runs 

100 """ 

101 self.__stats = {} 

102 

103 def pre_setup(self, step, level_number): 

104 """ 

105 Default routine called before setup starts 

106 

107 Args: 

108 step (pySDC.Step.step): the current step 

109 level_number (int): the current level number 

110 """ 

111 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

112 

113 def pre_run(self, step, level_number): 

114 """ 

115 Default routine called before time-loop starts 

116 

117 Args: 

118 step (pySDC.Step.step): the current step 

119 level_number (int): the current level number 

120 """ 

121 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

122 

123 def pre_predict(self, step, level_number): 

124 """ 

125 Default routine called before predictor starts 

126 

127 Args: 

128 step (pySDC.Step.step): the current step 

129 level_number (int): the current level number 

130 """ 

131 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

132 

133 def pre_step(self, step, level_number): 

134 """ 

135 Hook called before each step 

136 

137 Args: 

138 step (pySDC.Step.step): the current step 

139 level_number (int): the current level number 

140 """ 

141 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

142 

143 def pre_iteration(self, step, level_number): 

144 """ 

145 Default routine called before iteration starts 

146 

147 Args: 

148 step (pySDC.Step.step): the current step 

149 level_number (int): the current level number 

150 """ 

151 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

152 

153 def pre_sweep(self, step, level_number): 

154 """ 

155 Default routine called before sweep starts 

156 

157 Args: 

158 step (pySDC.Step.step): the current step 

159 level_number (int): the current level number 

160 """ 

161 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

162 

163 def pre_comm(self, step, level_number): 

164 """ 

165 Default routine called before communication starts 

166 

167 Args: 

168 step (pySDC.Step.step): the current step 

169 level_number (int): the current level number 

170 """ 

171 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

172 

173 def post_comm(self, step, level_number, add_to_stats=False): 

174 """ 

175 Default routine called after each communication 

176 

177 Args: 

178 step (pySDC.Step.step): the current step 

179 level_number (int): the current level number 

180 add_to_stats (bool): set if result should go to stats object 

181 """ 

182 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

183 

184 def post_sweep(self, step, level_number): 

185 """ 

186 Default routine called after each sweep 

187 

188 Args: 

189 step (pySDC.Step.step): the current step 

190 level_number (int): the current level number 

191 """ 

192 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

193 

194 def post_iteration(self, step, level_number): 

195 """ 

196 Default routine called after each iteration 

197 

198 Args: 

199 step (pySDC.Step.step): the current step 

200 level_number (int): the current level number 

201 """ 

202 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

203 

204 def post_step(self, step, level_number): 

205 """ 

206 Default routine called after each step or block 

207 

208 Args: 

209 step (pySDC.Step.step): the current step 

210 level_number (int): the current level number 

211 """ 

212 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

213 

214 def post_predict(self, step, level_number): 

215 """ 

216 Default routine called after each predictor 

217 

218 Args: 

219 step (pySDC.Step.step): the current step 

220 level_number (int): the current level number 

221 """ 

222 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

223 

224 def post_run(self, step, level_number): 

225 """ 

226 Default routine called after each run 

227 

228 Args: 

229 step (pySDC.Step.step): the current step 

230 level_number (int): the current level number 

231 """ 

232 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0 

233 

234 def post_setup(self, step, level_number): 

235 """ 

236 Default routine called after setup 

237 

238 Args: 

239 step (pySDC.Step.step): the current step 

240 level_number (int): the current level number 

241 """ 

242 self.__num_restarts = step.status.get('restarts_in_a_row') if step is not None else 0