Coverage for src/beamme/four_c/element_data.py: 94%

31 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-08 11:03 +0000

1# The MIT License (MIT) 

2# 

3# Copyright (c) 2018-2026 BeamMe Authors 

4# 

5# Permission is hereby granted, free of charge, to any person obtaining a copy 

6# of this software and associated documentation files (the "Software"), to deal 

7# in the Software without restriction, including without limitation the rights 

8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 

9# copies of the Software, and to permit persons to whom the Software is 

10# furnished to do so, subject to the following conditions: 

11# 

12# The above copyright notice and this permission notice shall be included in 

13# all copies or substantial portions of the Software. 

14# 

15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 

16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 

17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 

18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 

19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 

20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 

21# THE SOFTWARE. 

22"""Define a data class for 4C element data.""" 

23 

24from dataclasses import dataclass as _dataclass 

25from dataclasses import field as _field 

26from typing import Any as _Any 

27 

28import numpy as _np 

29from numpy.typing import NDArray as _NDArray 

30 

31from beamme.utils.data_structures import ( 

32 compare_nested_dicts_or_lists as _compare_nested_dicts_or_lists, 

33) 

34 

35 

36@_dataclass(eq=False) 

37class FourCElementData: 

38 """Class that contains the data for a 4C element block.""" 

39 

40 four_c_type: str 

41 four_c_cell: str 

42 element_technology: dict[str, _Any] = _field(default_factory=dict) 

43 

44 def get_legacy_dict( 

45 self, element_id, connectivity, element_material_id, additional_element_data 

46 ) -> dict: 

47 """Return the dictionary to write this element data to a legacy element 

48 definition in the input file.""" 

49 

50 return { 

51 "id": element_id + 1, 

52 "cell": { 

53 "type": self.four_c_cell, 

54 "connectivity": connectivity + 1, 

55 }, 

56 "data": { 

57 "type": self.four_c_type, 

58 **( 

59 {"MAT": element_material_id + 1} 

60 if element_material_id != -1 

61 else {} 

62 ), 

63 **self.element_technology, 

64 **(additional_element_data or {}), 

65 }, 

66 } 

67 

68 def __eq__(self, other) -> bool: 

69 """Check if two 4C element data objects are equal.""" 

70 if not isinstance(other, FourCElementData): 

71 return False 

72 if self.four_c_cell != other.four_c_cell: 

73 return False 

74 if self.four_c_type != other.four_c_type: 

75 return False 

76 if not _compare_nested_dicts_or_lists( 

77 self.element_technology, other.element_technology 

78 ): 

79 return False 

80 return True 

81 

82 

83def four_c_element_data_from_legacy_dict( 

84 legacy_dict: dict, 

85) -> tuple[FourCElementData, int, _NDArray, int]: 

86 """Extract the 4C element data from a legacy element definition in the 

87 input file. 

88 

89 Args: 

90 legacy_dict: The legacy element definition in the input file, will be modified in place. 

91 

92 Returns: 

93 A tuple containing the 4C element data, the element ID, the connectivity, and the material ID. 

94 """ 

95 

96 element_id = legacy_dict["id"] 

97 connectivity = _np.array(legacy_dict["cell"]["connectivity"], dtype=int) - 1 

98 four_c_cell = legacy_dict["cell"]["type"] 

99 

100 # Since we directly store `legacy_dict["data"]` as the element technology data, 

101 # the material ID and four_c_type have to be removed from the `legacy_dict["data"]` 

102 # dictionary, thus the `pop`. 

103 material_id = legacy_dict["data"].pop("MAT", 0) - 1 

104 four_c_type = legacy_dict["data"].pop("type") 

105 

106 data = FourCElementData( 

107 four_c_type=four_c_type, 

108 four_c_cell=four_c_cell, 

109 element_technology=legacy_dict["data"], 

110 ) 

111 

112 return data, element_id, connectivity, material_id