Coverage for mpcforces_extractor\datastructure\rigids.py: 98%

48 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-13 12:05 +0100

1from typing import Dict, List 

2from enum import Enum 

3from mpcforces_extractor.datastructure.entities import Node, Element 

4from mpcforces_extractor.datastructure.subcases import Subcase 

5 

6 

7class MPC_CONFIG(Enum): 

8 """ 

9 Enum to represent the MPC configuration 

10 """ 

11 

12 RBE2 = 1 

13 RBE3 = 2 

14 

15 

16class MPC: 

17 """ 

18 This class is a Multiple Point Constraint (MPC) class that is used to store the nodes and the dofs 

19 """ 

20 

21 config_2_id_2_instance: Dict[int, "MPC"] = {} 

22 

23 def __init__( 

24 self, 

25 *, # fixes the too many positional arguments error from the linter by forcing the use of keyword arguments 

26 element_id: int, 

27 mpc_config: MPC_CONFIG, 

28 master_node: Node, 

29 nodes: List, 

30 dofs: str, 

31 ): 

32 self.element_id: int = element_id 

33 self.mpc_config: MPC_CONFIG = mpc_config 

34 if master_node is None: 

35 print("Master_node2coords is None for element_id", element_id) 

36 self.master_node = master_node 

37 self.nodes: List = nodes 

38 self.dofs: int = dofs 

39 self.part_id2node_ids = {} 

40 

41 # config_2_id_2_instance 

42 if mpc_config.value not in MPC.config_2_id_2_instance: 

43 MPC.config_2_id_2_instance[mpc_config.value] = {} 

44 

45 if element_id in MPC.config_2_id_2_instance[mpc_config.value]: 

46 print("MPC element_id already exists", element_id) 

47 MPC.config_2_id_2_instance[mpc_config.value][element_id] = self 

48 

49 @staticmethod 

50 def reset(): 

51 """ 

52 This method is used to reset the instances 

53 """ 

54 MPC.config_2_id_2_instance = {} 

55 

56 def get_part_id2force(self, subcase: Subcase) -> Dict: 

57 """ 

58 This method is used to get the forces for each part of the MPC (connected slave nodes) 

59 """ 

60 

61 if not self.part_id2node_ids: 

62 # Connected groups of nodes - get then the intersection with the slave nodes 

63 part_id2connected_node_ids = Element.get_part_id2node_ids_graph() 

64 part_id2node_ids = {} 

65 mpc_node_ids = [node.id for node in self.nodes] 

66 mpc_node_ids.append(self.master_node.id) 

67 for part_id, node_ids in part_id2connected_node_ids.items(): 

68 part_id2node_ids[part_id] = list( 

69 set(node_ids).intersection(mpc_node_ids) 

70 ) 

71 

72 self.part_id2node_ids = part_id2node_ids 

73 

74 # Calculate the summed forces for each part 

75 part_id2forces = {} 

76 for part_id, node_ids in self.part_id2node_ids.items(): 

77 sum_forces = [0, 0, 0] 

78 if subcase is not None: 

79 sum_forces = subcase.get_sum_forces(node_ids) 

80 part_id2forces[part_id] = sum_forces 

81 return part_id2forces 

82 

83 def get_subcase_id2part_id2force(self) -> Dict: 

84 """ 

85 This method is used to get the forces for each part of the MPC (connected slave nodes) 

86 """ 

87 

88 subcase_id2part_id2forces = {} 

89 for subcase in Subcase.subcases: 

90 part_id2forces = self.get_part_id2force(subcase) 

91 subcase_id2part_id2forces[subcase.subcase_id] = part_id2forces 

92 return subcase_id2part_id2forces