Coverage for src/meshpy/mesh_creation_functions/beam_arc.py: 95%

41 statements  

« prev     ^ index     » next       coverage.py v7.9.0, created at 2025-06-13 04:26 +0000

1# The MIT License (MIT) 

2# 

3# Copyright (c) 2018-2025 MeshPy 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"""Functions to create beam meshes along arcs.""" 

23 

24import numpy as _np 

25 

26from meshpy.core.conf import mpy as _mpy 

27from meshpy.core.rotation import Rotation as _Rotation 

28from meshpy.mesh_creation_functions.beam_generic import ( 

29 create_beam_mesh_generic as _create_beam_mesh_generic, 

30) 

31 

32 

33def create_beam_mesh_arc_segment_via_rotation( 

34 mesh, beam_class, material, center, axis_rotation, radius, angle, **kwargs 

35): 

36 """Generate a circular segment of beam elements. 

37 

38 The circular segment is defined via a rotation, specifying the "initial" 

39 triad of the beam at the beginning of the arc. 

40 

41 This function exists for compatibility reasons with older MeshPy implementations. 

42 The user is encouraged to use the newer implementation create_beam_mesh_arc_segment_via_axis 

43 

44 Args 

45 ---- 

46 mesh: Mesh 

47 Mesh that the arc segment will be added to. 

48 beam_class: Beam 

49 Class of beam that will be used for this line. 

50 material: Material 

51 Material for this segment. 

52 center: _np.array, list 

53 Center of the arc. 

54 axis_rotation: Rotation 

55 This rotation defines the spatial orientation of the arc. 

56 The 3rd base vector of this rotation is the rotation axis of the arc 

57 segment. The segment starts in the direction of the 1st basis vector 

58 and the starting point is along the 2nd basis vector. 

59 radius: float 

60 The radius of the segment. 

61 angle: float 

62 The central angle of this segment in radians. 

63 

64 **kwargs (for all of them look into create_beam_mesh_function) 

65 ---- 

66 n_el: int 

67 Number of equally spaced beam elements along the line. Defaults to 1. 

68 Mutually exclusive with l_el. 

69 l_el: float 

70 Desired length of beam elements. Mutually exclusive with n_el. 

71 Be aware, that this length might not be achieved, if the elements are 

72 warped after they are created. 

73 

74 Return 

75 ---- 

76 return_set: GeometryName 

77 Set with the 'start' and 'end' node of the line. Also a 'line' set 

78 with all nodes of the line. 

79 """ 

80 

81 # Convert the input to the one for create_beam_mesh_arc_segment_via_axis 

82 axis = axis_rotation * [0, 0, 1] 

83 start_point = center + radius * (axis_rotation * [0, -1, 0]) 

84 return create_beam_mesh_arc_segment_via_axis( 

85 mesh, beam_class, material, axis, center, start_point, angle, **kwargs 

86 ) 

87 

88 

89def create_beam_mesh_arc_segment_via_axis( 

90 mesh, 

91 beam_class, 

92 material, 

93 axis, 

94 axis_point, 

95 start_point, 

96 angle, 

97 **kwargs, 

98): 

99 """Generate a circular segment of beam elements. 

100 

101 The arc is defined via a rotation axis, a point on the rotation axis a starting 

102 point, as well as the angle of the arc segment. 

103 

104 Args 

105 ---- 

106 mesh: Mesh 

107 Mesh that the arc segment will be added to. 

108 beam_class: Beam 

109 Class of beam that will be used for this line. 

110 material: Material 

111 Material for this segment. 

112 axis: _np.array, list 

113 Rotation axis of the arc. 

114 axis_point: _np.array, list 

115 Point lying on the rotation axis. Does not have to be the center of the arc. 

116 start_point: _np.array, list 

117 Start point of the arc. 

118 angle: float 

119 The central angle of this segment in radians. 

120 

121 **kwargs (for all of them look into create_beam_mesh_function) 

122 ---- 

123 n_el: int 

124 Number of equally spaced beam elements along the line. Defaults to 1. 

125 Mutually exclusive with l_el. 

126 l_el: float 

127 Desired length of beam elements. Mutually exclusive with n_el. 

128 Be aware, that this length might not be achieved, if the elements are 

129 warped after they are created. 

130 

131 Return 

132 ---- 

133 return_set: GeometryName 

134 Set with the 'start' and 'end' node of the line. Also a 'line' set 

135 with all nodes of the line. 

136 """ 

137 

138 # The angle can not be negative with the current implementation. 

139 if angle <= 0.0: 

140 raise ValueError( 

141 "The angle for a beam arc segment has to be a positive number!" 

142 ) 

143 

144 # Shortest distance from the given point to the axis of rotation gives 

145 # the "center" of the arc 

146 axis = _np.asarray(axis) 

147 axis_point = _np.asarray(axis_point) 

148 start_point = _np.asarray(start_point) 

149 

150 axis = axis / _np.linalg.norm(axis) 

151 diff = start_point - axis_point 

152 distance = diff - _np.dot(_np.dot(diff, axis), axis) 

153 radius = _np.linalg.norm(distance) 

154 center = start_point - distance 

155 

156 # Get the rotation at the start 

157 # No need to check the start node here, as eventual rotation offsets in 

158 # tangential direction will be covered by the create beam functionality. 

159 tangent = _np.cross(axis, distance) 

160 tangent /= _np.linalg.norm(tangent) 

161 start_rotation = _Rotation.from_rotation_matrix( 

162 _np.transpose(_np.array([tangent, -distance / radius, axis])) 

163 ) 

164 

165 def get_beam_geometry(alpha, beta): 

166 """Return a function for the position and rotation along the beam 

167 axis.""" 

168 

169 def beam_function(xi): 

170 """Return a point and the triad on the beams axis for a given 

171 parameter coordinate xi.""" 

172 phi = 0.5 * (xi + 1) * (beta - alpha) + alpha 

173 arc_rotation = _Rotation(axis, phi) 

174 rot = arc_rotation * start_rotation 

175 pos = center + arc_rotation * distance 

176 return (pos, rot, phi * radius) 

177 

178 return beam_function 

179 

180 # Create the beam in the mesh 

181 return _create_beam_mesh_generic( 

182 mesh, 

183 beam_class=beam_class, 

184 material=material, 

185 function_generator=get_beam_geometry, 

186 interval=[0.0, angle], 

187 interval_length=angle * radius, 

188 **kwargs, 

189 ) 

190 

191 

192def create_beam_mesh_arc_segment_2d( 

193 mesh, beam_class, material, center, radius, phi_start, phi_end, **kwargs 

194): 

195 """Generate a circular segment of beam elements in the x-y plane. 

196 

197 Args 

198 ---- 

199 mesh: Mesh 

200 Mesh that the arc segment will be added to. 

201 beam_class: Beam 

202 Class of beam that will be used for this line. 

203 material: Material 

204 Material for this segment. 

205 center: _np.array, list 

206 Center of the arc. If the z component is not 0, an error will be 

207 thrown. 

208 radius: float 

209 The radius of the segment. 

210 phi_start, phi_end: float 

211 The start and end angles of the arc w.r.t the x-axis. If the start 

212 angle is larger than the end angle the beam faces in counter-clockwise 

213 direction, and if the start angle is smaller than the end angle, the 

214 beam faces in clockwise direction. 

215 

216 **kwargs (for all of them look into create_beam_mesh_function) 

217 ---- 

218 n_el: int 

219 Number of equally spaced beam elements along the line. Defaults to 1. 

220 Mutually exclusive with l_el. 

221 l_el: float 

222 Desired length of beam elements. Mutually exclusive with n_el. 

223 Be aware, that this length might not be achieved, if the elements are 

224 warped after they are created. 

225 

226 Return 

227 ---- 

228 return_set: GeometryName 

229 Set with the 'start' and 'end' node of the line. Also a 'line' set 

230 with all nodes of the line. 

231 """ 

232 

233 # The center point has to be on the x-y plane. 

234 if _np.abs(center[2]) > _mpy.eps_pos: 

235 raise ValueError("The z-value of center has to be 0!") 

236 

237 # Check if the beam is in clockwise or counter clockwise direction. 

238 angle = phi_end - phi_start 

239 axis = _np.array([0, 0, 1]) 

240 start_point = center + radius * (_Rotation(axis, phi_start) * [1, 0, 0]) 

241 

242 counter_clockwise = _np.sign(angle) == 1 

243 if not counter_clockwise: 

244 # If the beam is not in counter clockwise direction, we have to flip 

245 # the rotation axis. 

246 axis = -1.0 * axis 

247 

248 return create_beam_mesh_arc_segment_via_axis( 

249 mesh, 

250 beam_class, 

251 material, 

252 axis, 

253 center, 

254 start_point, 

255 _np.abs(angle), 

256 **kwargs, 

257 )