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
« 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."""
24import numpy as _np
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)
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.
38 The circular segment is defined via a rotation, specifying the "initial"
39 triad of the beam at the beginning of the arc.
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
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.
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.
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 """
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 )
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.
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.
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.
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.
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 """
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 )
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)
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
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 )
165 def get_beam_geometry(alpha, beta):
166 """Return a function for the position and rotation along the beam
167 axis."""
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)
178 return beam_function
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 )
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.
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.
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.
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 """
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!")
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])
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
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 )