44 _dot_product ,
55 _norm ,
66 _find_min_dist ,
7+ _find_min_dist_cylinder_sphere ,
78 _find_slipping_elements ,
89 _node_to_element_mass_or_force ,
910 _elements_to_nodes_inplace ,
@@ -49,6 +50,13 @@ def _calculate_contact_forces_rod_cylinder(
4950 velocity_damping_coefficient : np .float64 ,
5051 friction_coefficient : np .float64 ,
5152) -> None :
53+ """
54+ Calculates the contact forces between a rod and a cylinder.
55+
56+ This function computes the linear and angular contact forces acting on both the rod and the cylinder
57+ when they come into contact. It considers spring-damper-based contact forces as well as friction.
58+ The forces are applied to the nodes of the rod and the center of mass of the cylinder.
59+ """
5260 # We already pass in only the first n_elem x
5361 n_points = x_collection_rod .shape [1 ]
5462 cylinder_total_contact_forces = np .zeros ((3 ))
@@ -174,6 +182,9 @@ def _calculate_contact_forces_rod_rod(
174182 contact_k : np .float64 ,
175183 contact_nu : np .float64 ,
176184) -> None :
185+ """
186+ Calculates the contact forces between two rods.
187+ """
177188 # We already pass in only the first n_elem x
178189 n_points_rod_one = x_collection_rod_one .shape [1 ]
179190 n_points_rod_two = x_collection_rod_two .shape [1 ]
@@ -283,6 +294,12 @@ def _calculate_contact_forces_self_rod(
283294 contact_k : np .float64 ,
284295 contact_nu : np .float64 ,
285296) -> None :
297+ """
298+ Calculates the self-contact forces within a single rod.
299+
300+ This function prevents self-penetration of a rod by calculating contact forces between different elements
301+ of the same rod. A skip parameter is used to avoid checking adjacent elements.
302+ """
286303 # We already pass in only the first n_elem x
287304 n_points_rod = x_collection_rod .shape [1 ]
288305 edge_collection_rod_one = _batch_product_k_ik_to_ik (length_rod , tangent_rod )
@@ -364,41 +381,44 @@ def _calculate_contact_forces_self_rod(
364381def _calculate_contact_forces_rod_sphere (
365382 x_collection_rod : NDArray [np .float64 ],
366383 edge_collection_rod : NDArray [np .float64 ],
367- x_sphere_center : NDArray [np .float64 ],
368- x_sphere_tip : NDArray [np .float64 ],
369- edge_sphere : NDArray [np .float64 ],
384+ x_sphere : NDArray [np .float64 ],
370385 radii_sum : NDArray [np .float64 ],
371386 length_sum : NDArray [np .float64 ],
372- internal_forces_rod : NDArray [np .float64 ],
373387 external_forces_rod : NDArray [np .float64 ],
374388 external_forces_sphere : NDArray [np .float64 ],
375- external_torques_sphere : NDArray [np .float64 ],
376- sphere_director_collection : NDArray [np .float64 ],
377389 velocity_rod : NDArray [np .float64 ],
378390 velocity_sphere : NDArray [np .float64 ],
379391 contact_k : np .float64 ,
380392 contact_nu : np .float64 ,
381393 velocity_damping_coefficient : np .float64 ,
382394 friction_coefficient : np .float64 ,
383395) -> None :
396+ """
397+ Calculates the contact forces between a rod and a sphere.
398+
399+ This function computes the linear and angular contact forces acting on both the rod and the sphere
400+ when they come into contact. It considers spring-damper-based contact forces as well as friction.
401+ The forces are applied to the nodes of the rod and the center of mass of the sphere.
402+ """
384403 # We already pass in only the first n_elem x
385404 n_points = x_collection_rod .shape [1 ]
386405 sphere_total_contact_forces = np .zeros ((3 ))
387- sphere_total_contact_torques = np .zeros ((3 ))
388406 for i in range (n_points ):
389407 # Element-wise bounding box
390408 x_selected = x_collection_rod [..., i ]
391409 # x_sphere is already a (,) array from outside
392- del_x = x_selected - x_sphere_tip
410+ del_x = x_selected - x_sphere
393411 norm_del_x = _norm (del_x )
394412
395413 # If outside then don't process
396414 if norm_del_x >= (radii_sum [i ] + length_sum [i ]):
397415 continue
398416
399417 # find the shortest line segment between the two centerline
400- distance_vector , x_sphere_contact_point , _ = _find_min_dist (
401- x_selected , edge_collection_rod [..., i ], x_sphere_tip , edge_sphere
418+ distance_vector , _ , _ = _find_min_dist_cylinder_sphere (
419+ x_selected ,
420+ edge_collection_rod [..., i ],
421+ x_sphere ,
402422 )
403423 distance_vector_length = _norm (distance_vector )
404424 distance_vector /= distance_vector_length
@@ -453,37 +473,22 @@ def _calculate_contact_forces_rod_sphere(
453473 # Update contact force
454474 net_contact_force += friction_force
455475
456- # Torques acting on the cylinder
457- moment_arm = x_sphere_contact_point - x_sphere_center
458-
459476 # Add it to the rods at the end of the day
460477 if i == 0 :
461478 external_forces_rod [..., i ] -= 2 / 3 * net_contact_force
462479 external_forces_rod [..., i + 1 ] -= 4 / 3 * net_contact_force
463480 sphere_total_contact_forces += 2.0 * net_contact_force
464- sphere_total_contact_torques += np .cross (
465- moment_arm , 2.0 * net_contact_force
466- )
467481 elif i == n_points - 1 :
468482 external_forces_rod [..., i ] -= 4 / 3 * net_contact_force
469483 external_forces_rod [..., i + 1 ] -= 2 / 3 * net_contact_force
470484 sphere_total_contact_forces += 2.0 * net_contact_force
471- sphere_total_contact_torques += np .cross (
472- moment_arm , 2.0 * net_contact_force
473- )
474485 else :
475486 external_forces_rod [..., i ] -= net_contact_force
476487 external_forces_rod [..., i + 1 ] -= net_contact_force
477488 sphere_total_contact_forces += 2.0 * net_contact_force
478- sphere_total_contact_torques += np .cross (
479- moment_arm , 2.0 * net_contact_force
480- )
481489
482490 # Update the cylinder external forces and torques
483491 external_forces_sphere [..., 0 ] += sphere_total_contact_forces
484- external_torques_sphere [..., 0 ] += (
485- sphere_director_collection @ sphere_total_contact_torques
486- )
487492
488493
489494@njit (cache = True ) # type: ignore
@@ -501,17 +506,16 @@ def _calculate_contact_forces_rod_plane(
501506 external_forces : NDArray [np .float64 ],
502507) -> tuple [NDArray [np .float64 ], NDArray [np .intp ]]:
503508 """
504- This function computes the plane force response on the element, in the
505- case of contact. Contact model given in Eqn 4.8 Gazzola et. al. RSoS 2018 paper
506- is used.
509+ Calculates the contact forces between a rod and a plane.
510+
511+ This function computes the contact force exerted by a flat plane on a rod.
512+ It includes a linear spring-damper model for the normal force to handle penetration
513+ and a response to prevent the rod from passing through the plane.
514+ It returns the magnitude of the plane response force and indices of elements not in contact.
507515
508- Parameters
509- ----------
510- system
516+ Contact model given in Eqn 4.8 Gazzola et. al. RSoS 2018 paper
517+ is used.
511518
512- Returns
513- -------
514- magnitude of the plane response
515519 """
516520
517521 # Compute plane response force
@@ -597,6 +601,9 @@ def _calculate_contact_forces_rod_plane_with_anisotropic_friction(
597601 internal_torques : NDArray [np .float64 ],
598602 external_torques : NDArray [np .float64 ],
599603) -> None :
604+ """
605+ Calculates contact forces between a rod and a plane with anisotropic friction.
606+ """
600607 (
601608 plane_response_force_mag ,
602609 no_contact_point_idx ,
@@ -796,6 +803,9 @@ def _calculate_contact_forces_cylinder_plane(
796803 velocity_collection : NDArray [np .float64 ],
797804 external_forces : NDArray [np .float64 ],
798805) -> tuple [NDArray [np .float64 ], NDArray [np .intp ]]:
806+ """
807+ Calculates the contact forces between a cylinder and a plane.
808+ """
799809
800810 # Compute plane response force
801811 # total_forces = system.internal_forces + system.external_forces
0 commit comments