Coverage for mpcforces_extractor\writer\summary_writer.py: 81%

74 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-06 21:34 +0100

1import os 

2import time 

3from typing import Optional 

4from mpcforces_extractor.reader.modelreaders import FemFileReader 

5from mpcforces_extractor.datastructure.loads import Force, Moment 

6from mpcforces_extractor.datastructure.rigids import MPC 

7from mpcforces_extractor.force_extractor import MPCForceExtractor 

8 

9 

10class SummaryWriter: 

11 """ 

12 This class is used to write the summary of the forces extracted from the MPC forces file 

13 """ 

14 

15 def __init__( 

16 self, instance: MPCForceExtractor, output_folder: Optional[str] = None 

17 ): 

18 self.instance = instance 

19 if output_folder: 

20 self.output_path = os.path.join(output_folder, "summary.txt") 

21 else: 

22 self.output_path = None 

23 self.lines = [] 

24 self.start_time = time.time() 

25 

26 def add_header(self): 

27 """ 

28 This method adds the header to the summary 

29 """ 

30 timestamp = time.time() 

31 local_time = time.localtime(timestamp) 

32 formatted_time = time.strftime("%Y-%m-%d %H:%M:%S", local_time) 

33 

34 self.lines.append("Summary of the MPC forces extraction\n") 

35 self.lines.append(f"Date: {formatted_time}\n") 

36 self.lines.append(f"Input FEM file: {self.instance.fem_file_path}\n") 

37 self.lines.append(f"Input MPC forces file: {self.instance.mpc_file_path}\n") 

38 self.lines.append("\n") 

39 

40 def add_mpc_lines(self): 

41 """ 

42 This method adds the lines for each MPC element to the summary 

43 """ 

44 for mpc in self.instance.reader.rigid_elements: 

45 self.add_mpc_line(mpc) 

46 

47 def add_mpc_line(self, mpc: MPC) -> None: 

48 """ 

49 Add info for a single MPC element 

50 """ 

51 self.lines.append(f"Rigid Element ID: {mpc.element_id}\n") 

52 self.lines.append(f" MPC Config: {mpc.mpc_config.name}\n") 

53 

54 # Forces present 

55 for _, load in FemFileReader.load_id2load.items(): 

56 load_x = round(load.compenents[0], 3) 

57 load_y = round(load.compenents[1], 3) 

58 load_z = round(load.compenents[2], 3) 

59 # check if load is instance of force or a moment 

60 load_type = "None" 

61 if isinstance(load, Force): 

62 load_type = "Force" 

63 if isinstance(load, Moment): 

64 load_type = "Moment" 

65 

66 if load.node_id in [mpc.master_node.id]: 

67 self.lines.append( 

68 f" {load_type} at Master ID: {load.id}; {load_x},{load_y},{load_z}\n" 

69 ) 

70 if load.node_id in [node.id for node in mpc.nodes]: 

71 self.lines.append( 

72 f" {load_type} at Slave ID: {load.id}; {load_x},{load_y},{load_z}\n" 

73 ) 

74 

75 # 1D elements associated with the master node 

76 for element1D in self.instance.reader.elements_1D: 

77 if mpc.master_node in [element1D.node1, element1D.node2]: 

78 self.lines.append( 

79 f" 1D Element ID: {element1D.id} associated with the master Node\n" 

80 ) 

81 master_node = mpc.master_node 

82 

83 self.lines.append(f" Master Node ID: {master_node.id}\n") 

84 self.lines.append(f" Master Node Coords: {master_node.coords}\n") 

85 self.lines.append(f" Slave Nodes: {len(mpc.nodes)}\n") 

86 

87 # add the force data 

88 for subcase in self.instance.subcases: 

89 subcase_id = subcase.subcase_id 

90 subcase_time = subcase.time 

91 self.lines.append(f" Subcase ID: {subcase_id}\n") 

92 self.lines.append(f" Time: {subcase_time}\n") 

93 for part_id, forces in mpc.get_part_id2force(subcase).items(): 

94 self.lines.append(f" Part ID: {part_id}\n") 

95 node_ids = mpc.part_id2node_ids[part_id] 

96 self.lines.append( 

97 f" First 5 Slave Nodes for Location {node_ids[1:6]}\n" 

98 ) 

99 node_ids = mpc.part_id2node_ids[part_id] 

100 self.lines.append(f" Slave Nodes: {len(node_ids)}\n") 

101 force_names = ["FX", "FY", "FZ", "MX", "MY", "MZ"] 

102 for i, force in enumerate(forces): 

103 self.lines.append(f" {force_names[i]}: {force:.3f}\n") 

104 

105 self.lines.append("\n") 

106 

107 def write_lines(self): 

108 """ 

109 This method writes the lines to the file 

110 """ 

111 if not self.output_path: 

112 print("No output path specified - not writing summary") 

113 return 

114 

115 with open(self.output_path, "w", encoding="utf-8") as file: 

116 for line in self.lines: 

117 file.write(line) 

118 print("Summary written to", self.output_path) 

119 print("..took ", round(time.time() - self.start_time, 2), "seconds")