Coverage for dragonfly_sim/utils/data_handler.py: 36%

66 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-17 03:37 +0000

1import os 

2import numpy as np 

3from matplotlib import pyplot as plt 

4 

5def split_list_of_tuples_into_separate_lists(inp_list, iter_acceptance_list=None): 

6 list_of_lists = [] 

7 for i in range(len(inp_list[0])): 

8 single_list_i = [element[i] for element in inp_list] 

9 

10 if i == 0 and iter_acceptance_list is not None: 

11 elements_to_include = np.isin(single_list_i, iter_acceptance_list) 

12 

13 if iter_acceptance_list is not None: 

14 single_list_i = list(np.array(single_list_i)[elements_to_include]) 

15 

16 list_of_lists += [single_list_i] 

17 return list_of_lists 

18 

19 

20class DataStore(): 

21 def __init__(self): 

22 # Initialize arrays that store outputs 

23 

24 # Relative residual norms eta = ||r||/||u||. These, not absolute norms, 

25 # are what to plot or threshold on: eta is free of the sqrt(n_dofs) and 

26 # state-magnitude factors that make absolute norms incomparable 

27 # between meshes. 

28 self.fom_relative_residuals = [] 

29 

30 # objective function histories 

31 self.FOM_force_coefficients = [] 

32 # Dimensional (unnormalized) FOM lift/drag/moment forces, same 

33 # (eval_idx, D, L, M_1, ...) tuple layout and eval_idx indexing as 

34 # FOM_force_coefficients' (eval_idx, c_d, c_l, c_m_1, ...), with one 

35 # moment entry per moment of the postprocessor, in its order. 

36 self.FOM_forces = [] 

37 

38 # Parameter vector histories 

39 self.parameter_vectors_per_iteration = [] 

40 

41 # Wall times of the full-order model 

42 self.FOM_walltime = [] 

43 

44 # POD reduced-order model (core/reduced_order_model.py), per ROM solve: 

45 # wall time, eta, (eval_idx, c_d, c_l, c_m_1, ...) like 

46 # FOM_force_coefficients, whether eta met the acceptance threshold, 

47 # and (eval_idx, dc_d, dc_l, dc_m_1, ...) ROM - FOM when the FOM also ran; 

48 # the snapshot singular values after every snapshot added 

49 self.ROM_walltime = [] 

50 self.rom_relative_residuals = [] 

51 self.ROM_force_coefficients = [] 

52 self.ROM_meets_threshold = [] 

53 self.rom_coefficient_errors = [] 

54 self.global_snapshot_sing_vals_per_iteration = [] 

55 

56 # Per adjoint solve (one per output row of a derivative evaluation): 

57 # (eval_idx, 'rom' or 'fom', wall time). 'rom' is the reduced adjoint 

58 # of an accepted ROM solution, 'fom' the full-order adjoint. 

59 self.adjoint_solves = [] 

60 

61 # Number of DoFs in simulation 

62 self.fe_dofs = 0 

63 # Number of design parameters in optimization 

64 self.num_var = 0 

65 

66 def compile_store_in_dict(self): 

67 data_dict = {} 

68 for data in vars(self): 

69 # print(data) 

70 # print(self.__dict__[str(data)]) 

71 data_dict[str(data)] = self.__dict__[str(data)] 

72 return data_dict 

73 

74 def write_store_to_numpy_file(self, save_folder="Result_dicts", save_filename="POD_deployment.npy"): 

75 save_location = save_folder + "/" + save_filename 

76 os.makedirs(save_folder, exist_ok=True) 

77 # create dictionary with all data 

78 data_dict = self.compile_store_in_dict() 

79 # save data_dict to location 

80 np.save(save_location, data_dict) 

81 print("Saved data dictionary to {}".format(save_location)) 

82 

83 def open_dict_and_import_data(self, file_folder="Result_dicts", filename="POD_deployment.npy"): 

84 file_location = file_folder + "/" + filename 

85 data_dict = np.load(file_location, allow_pickle=True) 

86 data_dict = data_dict.item() 

87 for key, value in data_dict.items(): 

88 setattr(self, key, value) 

89 

90 # TODO: Add routine to unpack input list(s) for plotting, move actual plotting routines to separate utility file 

91 

92 

93def plot_walltime_boxplots(data_stores, data_legend, yrange=(0, 3), show_yaxis_label=True): 

94 # One boxplot of the full-order-model wall times per data store, with a 

95 # horizontal line at the mean wall time pooled over all data stores 

96 fom_walltime_list = [] 

97 for data_store in data_stores: 

98 _, FOM_walltime = zip(*data_store.FOM_walltime) 

99 fom_walltime_list += [np.array(FOM_walltime)] 

100 

101 fig = plt.figure(figsize=(2.2,3.)) 

102 ax = fig.add_subplot(111) 

103 

104 fom_walltime_mean = np.mean(np.concatenate(fom_walltime_list)) 

105 ax.plot([0.5, len(data_stores)+0.5], [fom_walltime_mean, fom_walltime_mean], 'k', linewidth=3) 

106 

107 ax.boxplot(fom_walltime_list, widths=0.8) 

108 

109 # adding horizontal grid lines 

110 ax.yaxis.grid(True) 

111 # ax.set_yscale("log") 

112 ax.set_xticks([y + 1 for y in range(len(fom_walltime_list))], 

113 labels=data_legend) 

114 # ax.set_xlabel(r'Solver') 

115 if show_yaxis_label: 

116 ax.set_ylabel(r'Total wall time [s]') 

117 # else: 

118 # # frame = plt.gca() 

119 # ax.axes.yaxis.set_ticklabels([]) 

120 

121 ax.tick_params(axis='x', labelrotation=45) 

122 

123 for tick in ax.xaxis.get_major_ticks(): 

124 tick.label1.set_horizontalalignment('center') 

125 

126 ax.set_ylim(yrange[0], yrange[1]) 

127 

128 plt.subplots_adjust(left=0.23, right=0.955, bottom=0.19, top=0.95) 

129 # plt.rcParams.update({'font.size': 22}) 

130 plt.show() 

131 

132 

133# def plot_force_coefficients(data_stores)