|
9 | 9 | _node_to_element_velocity, |
10 | 10 | ) |
11 | 11 | from elastica._contact_functions import ( |
12 | | - _calculate_contact_forces_rod_plane, |
13 | | - _calculate_contact_forces_rod_plane_with_anisotropic_friction, |
14 | 12 | _calculate_contact_forces_cylinder_plane, |
15 | 13 | ) |
16 | 14 |
|
|
19 | 17 | from elastica.typing import SystemType, RodType, RigidBodyType |
20 | 18 |
|
21 | 19 |
|
22 | | -# base class for interaction |
23 | | -# only applies normal force no friction |
24 | | -class InteractionPlane(NoForces): |
25 | | - """ |
26 | | - The interaction plane class computes the plane reaction |
27 | | - force on a rod-like object. For more details regarding the contact module refer to |
28 | | - Eqn 4.8 of Gazzola et al. RSoS (2018). |
29 | | -
|
30 | | - Attributes |
31 | | - ---------- |
32 | | - k: float |
33 | | - Stiffness coefficient between the plane and the rod-like object. |
34 | | - nu: float |
35 | | - Dissipation coefficient between the plane and the rod-like object. |
36 | | - plane_origin: numpy.ndarray |
37 | | - 2D (dim, 1) array containing data with 'float' type. |
38 | | - Origin of the plane. |
39 | | - plane_normal: numpy.ndarray |
40 | | - 2D (dim, 1) array containing data with 'float' type. |
41 | | - The normal vector of the plane. |
42 | | - surface_tol: float |
43 | | - Penetration tolerance between the plane and the rod-like object. |
44 | | -
|
45 | | - """ |
46 | | - |
47 | | - def __init__( |
48 | | - self, |
49 | | - k: float, |
50 | | - nu: float, |
51 | | - plane_origin: NDArray[np.float64], |
52 | | - plane_normal: NDArray[np.float64], |
53 | | - ) -> None: |
54 | | - """ |
55 | | -
|
56 | | - Parameters |
57 | | - ---------- |
58 | | - k: float |
59 | | - Stiffness coefficient between the plane and the rod-like object. |
60 | | - nu: float |
61 | | - Dissipation coefficient between the plane and the rod-like object. |
62 | | - plane_origin: numpy.ndarray |
63 | | - 2D (dim, 1) array containing data with 'float' type. |
64 | | - Origin of the plane. |
65 | | - plane_normal: numpy.ndarray |
66 | | - 2D (dim, 1) array containing data with 'float' type. |
67 | | - The normal vector of the plane. |
68 | | - """ |
69 | | - self.k = np.float64(k) |
70 | | - self.nu = np.float64(nu) |
71 | | - self.surface_tol = np.float64(1e-4) |
72 | | - self.plane_origin = plane_origin.reshape(3, 1) |
73 | | - self.plane_normal = plane_normal.reshape(3) |
74 | | - |
75 | | - def apply_forces(self, system: RodType, time: np.float64 = np.float64(0.0)) -> None: |
76 | | - """ |
77 | | - In the case of contact with the plane, this function computes the plane reaction force on the element. |
78 | | -
|
79 | | - Parameters |
80 | | - ---------- |
81 | | - system: object |
82 | | - Rod-like object. |
83 | | -
|
84 | | - Returns |
85 | | - ------- |
86 | | - plane_response_force_mag : numpy.ndarray |
87 | | - 1D (blocksize) array containing data with 'float' type. |
88 | | - Magnitude of plane response force acting on rod-like object. |
89 | | - no_contact_point_idx : numpy.ndarray |
90 | | - 1D (blocksize) array containing data with 'int' type. |
91 | | - Index of rod-like object elements that are not in contact with the plane. |
92 | | - """ |
93 | | - return _calculate_contact_forces_rod_plane( |
94 | | - self.plane_origin, |
95 | | - self.plane_normal, |
96 | | - self.surface_tol, |
97 | | - self.k, |
98 | | - self.nu, |
99 | | - system.radius, |
100 | | - system.mass, |
101 | | - system.position_collection, |
102 | | - system.velocity_collection, |
103 | | - system.internal_forces, |
104 | | - system.external_forces, |
105 | | - ) |
106 | | - |
107 | | - |
108 | | -# class for anisotropic frictional plane |
109 | | -# NOTE: friction coefficients are passed as arrays in the order |
110 | | -# mu_forward : mu_backward : mu_sideways |
111 | | -# head is at x[0] and forward means head to tail |
112 | | -# same convention for kinetic and static |
113 | | -# mu named as to which direction it opposes |
114 | | -class AnisotropicFrictionalPlane(InteractionPlane): |
115 | | - """ |
116 | | - This anisotropic friction plane class is for computing |
117 | | - anisotropic friction forces on rods. |
118 | | - A detailed explanation of the implemented equations |
119 | | - can be found in Gazzola et al. RSoS. (2018). |
120 | | -
|
121 | | - Attributes |
122 | | - ---------- |
123 | | - k: float |
124 | | - Stiffness coefficient between the plane and the rod-like object. |
125 | | - nu: float |
126 | | - Dissipation coefficient between the plane and the rod-like object. |
127 | | - plane_origin: numpy.ndarray |
128 | | - 2D (dim, 1) array containing data with 'float' type. |
129 | | - Origin of the plane. |
130 | | - plane_normal: numpy.ndarray |
131 | | - 2D (dim, 1) array containing data with 'float' type. |
132 | | - The normal vector of the plane. |
133 | | - slip_velocity_tol: float |
134 | | - Velocity tolerance to determine if the element is slipping or not. |
135 | | - static_mu_array: numpy.ndarray |
136 | | - 1D (3,) array containing data with 'float' type. |
137 | | - [forward, backward, sideways] static friction coefficients. |
138 | | - kinetic_mu_array: numpy.ndarray |
139 | | - 1D (3,) array containing data with 'float' type. |
140 | | - [forward, backward, sideways] kinetic friction coefficients. |
141 | | - """ |
142 | | - |
143 | | - def __init__( |
144 | | - self, |
145 | | - k: float, |
146 | | - nu: float, |
147 | | - plane_origin: NDArray[np.float64], |
148 | | - plane_normal: NDArray[np.float64], |
149 | | - slip_velocity_tol: float, |
150 | | - static_mu_array: NDArray[np.float64], |
151 | | - kinetic_mu_array: NDArray[np.float64], |
152 | | - ) -> None: |
153 | | - """ |
154 | | -
|
155 | | - Parameters |
156 | | - ---------- |
157 | | - k: float |
158 | | - Stiffness coefficient between the plane and the rod-like object. |
159 | | - nu: float |
160 | | - Dissipation coefficient between the plane and the rod-like object. |
161 | | - plane_origin: numpy.ndarray |
162 | | - 2D (dim, 1) array containing data with 'float' type. |
163 | | - Origin of the plane. |
164 | | - plane_normal: numpy.ndarray |
165 | | - 2D (dim, 1) array containing data with 'float' type. |
166 | | - The normal vector of the plane. |
167 | | - slip_velocity_tol: float |
168 | | - Velocity tolerance to determine if the element is slipping or not. |
169 | | - static_mu_array: numpy.ndarray |
170 | | - 1D (3,) array containing data with 'float' type. |
171 | | - [forward, backward, sideways] static friction coefficients. |
172 | | - kinetic_mu_array: numpy.ndarray |
173 | | - 1D (3,) array containing data with 'float' type. |
174 | | - [forward, backward, sideways] kinetic friction coefficients. |
175 | | - """ |
176 | | - InteractionPlane.__init__(self, k, nu, plane_origin, plane_normal) |
177 | | - self.slip_velocity_tol = np.float64(slip_velocity_tol) |
178 | | - ( |
179 | | - self.static_mu_forward, |
180 | | - self.static_mu_backward, |
181 | | - self.static_mu_sideways, |
182 | | - ) = static_mu_array |
183 | | - ( |
184 | | - self.kinetic_mu_forward, |
185 | | - self.kinetic_mu_backward, |
186 | | - self.kinetic_mu_sideways, |
187 | | - ) = kinetic_mu_array |
188 | | - |
189 | | - # kinetic and static friction should separate functions |
190 | | - # for now putting them together to figure out common variables |
191 | | - def apply_forces( |
192 | | - self, system: "RodType | RigidBodyType", time: np.float64 = np.float64(0.0) |
193 | | - ) -> None: |
194 | | - """ |
195 | | - Call numba implementation to apply friction forces |
196 | | - Parameters |
197 | | - ---------- |
198 | | - system : RodType | RigidBodyType |
199 | | - time |
200 | | -
|
201 | | - """ |
202 | | - _calculate_contact_forces_rod_plane_with_anisotropic_friction( |
203 | | - self.plane_origin, |
204 | | - self.plane_normal, |
205 | | - self.surface_tol, |
206 | | - self.slip_velocity_tol, |
207 | | - self.k, |
208 | | - self.nu, |
209 | | - self.kinetic_mu_forward, |
210 | | - self.kinetic_mu_backward, |
211 | | - self.kinetic_mu_sideways, |
212 | | - self.static_mu_forward, |
213 | | - self.static_mu_backward, |
214 | | - self.static_mu_sideways, |
215 | | - system.radius, |
216 | | - system.mass, |
217 | | - system.tangents, |
218 | | - system.position_collection, |
219 | | - system.director_collection, |
220 | | - system.velocity_collection, |
221 | | - system.omega_collection, |
222 | | - system.internal_forces, |
223 | | - system.external_forces, |
224 | | - system.internal_torques, |
225 | | - system.external_torques, |
226 | | - ) |
227 | | - |
228 | | - |
229 | 20 | # Slender body module |
230 | 21 | @njit(cache=True) # type: ignore |
231 | 22 | def sum_over_elements(input: NDArray[np.float64]) -> np.float64: |
|
0 commit comments