Coverage for src / beamme / four_c / locsys_condition.py: 96%

24 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-21 12:57 +0000

1# The MIT License (MIT) 

2# 

3# Copyright (c) 2018-2025 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"""This file contains the wrapper for the LocSys condition for 4c.""" 

23 

24from typing import List as _List 

25from typing import Union as _Union 

26 

27from beamme.core.boundary_condition import BoundaryCondition as _BoundaryCondition 

28from beamme.core.conf import bme as _bme 

29from beamme.core.function import Function as _Function 

30from beamme.core.geometry_set import GeometrySet as _GeometrySet 

31from beamme.core.rotation import Rotation as _Rotation 

32from beamme.four_c.function_utility import ( 

33 ensure_length_of_function_array as _ensure_length_of_function_array, 

34) 

35 

36 

37class LocSysCondition(_BoundaryCondition): 

38 """This object represents a locsys condition in 4C. 

39 

40 It allows to rotate the local coordinate system used to apply 

41 Dirichlet boundary conditions. 

42 """ 

43 

44 def __init__( 

45 self, 

46 geometry_set: _GeometrySet, 

47 *, 

48 rotation: None | _Rotation = None, 

49 function_array: None | _List[_Union[_Function, int]] = None, 

50 update_node_position: bool = False, 

51 use_consistent_node_normal: bool = False, 

52 **kwargs, 

53 ): 

54 """Initialize the object. 

55 

56 Args: 

57 geometry_set: Geometry that this boundary condition acts on 

58 rotation: Object that represents the rotation of the coordinate system. 

59 function_array: 

60 - If a single function is provided, it is used to scale the entire rotation. 

61 - If three functions are provided, they represent the components of a rotation vector, 

62 in which case no explicit rotation should be passed. 

63 update_node_position: Flag to enable the updated node position 

64 use_consistent_node_normal: Flag to use a consistent node normal 

65 """ 

66 

67 # Check for invalid input arguments 

68 if ( 

69 function_array is not None 

70 and len(function_array) > 1 

71 and rotation is not None 

72 ): 

73 raise ValueError( 

74 "If more than a single function is provided in `function_array`, " 

75 "no explicit `rotation` should be given. Either provide " 

76 "a rotation with a single function (scaling), or three " 

77 "functions (rotation vector components) without rotation." 

78 ) 

79 

80 # Validate provided function array 

81 if function_array is None: 

82 function_array = [0, 0, 0] 

83 else: 

84 function_array = _ensure_length_of_function_array(function_array, 3) 

85 

86 # Validate provided rotation 

87 if rotation is None: 

88 rotation_vector = [1, 1, 1] 

89 else: 

90 rotation_vector = rotation.get_rotation_vector() 

91 

92 condition_dict = { 

93 "ROTANGLE": rotation_vector, 

94 "FUNCT": function_array, 

95 "USEUPDATEDNODEPOS": int(update_node_position), 

96 } 

97 

98 # Append the condition string with consistent normal type for line and surface geometry 

99 if ( 

100 geometry_set.geometry_type is _bme.geo.line 

101 or geometry_set.geometry_type is _bme.geo.surface 

102 ): 

103 condition_dict["USECONSISTENTNODENORMAL"] = int(use_consistent_node_normal) 

104 elif use_consistent_node_normal: 

105 raise ValueError( 

106 "The keyword use_consistent_node_normal only works for line and surface geometries." 

107 ) 

108 

109 super().__init__( 

110 geometry_set, data=condition_dict, bc_type=_bme.bc.locsys, **kwargs 

111 )