From 73788e61984d9921c6e111437fdf89fcdedfc5e3 Mon Sep 17 00:00:00 2001 From: Ali-7800 <47090295+Ali-7800@users.noreply.github.com> Date: Wed, 7 Feb 2024 14:04:05 -0600 Subject: [PATCH 1/3] Binder snake bug fix --- examples/Binder/2_Slithering_Snake.ipynb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/Binder/2_Slithering_Snake.ipynb b/examples/Binder/2_Slithering_Snake.ipynb index 23b0a94e..8dc05888 100644 --- a/examples/Binder/2_Slithering_Snake.ipynb +++ b/examples/Binder/2_Slithering_Snake.ipynb @@ -428,12 +428,12 @@ " # zero mean.\n", "\n", " # Number of steps in one period.\n", - " period_step = int(1.0 / (time_per_period[-1] - time_per_period[-2])) + 1\n", - " number_of_period = int(time_per_period[-1]) + 1\n", + " period_step = int(1.0 / (time_per_period[-1] - time_per_period[-2]))\n", + " number_of_period = int(time_per_period[-1])\n", "\n", " # Center of mass position averaged in one period\n", " center_of_mass_averaged_over_one_period = np.zeros((number_of_period - 2, 3))\n", - " for i in range(1, number_of_period - 1):\n", + " for i in range(1, number_of_period - 2):\n", " # position of center of mass averaged over one period\n", " center_of_mass_averaged_over_one_period[i - 1] = np.mean(\n", " center_of_mass[(i + 1) * period_step : (i + 2) * period_step]\n", @@ -722,7 +722,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3.9.12 ('base')", "language": "python", "name": "python3" }, @@ -736,7 +736,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.7" + "version": "3.9.12" + }, + "vscode": { + "interpreter": { + "hash": "69b409ac0f88f35940b70a7cc6f81becc62e64d51a49713aaa6660602c575037" + } } }, "nbformat": 4, From 4b85d328108490eba48aa2c98e78f1ca9c0bf7e6 Mon Sep 17 00:00:00 2001 From: Ali-7800 <47090295+Ali-7800@users.noreply.github.com> Date: Tue, 13 Feb 2024 16:53:48 -0600 Subject: [PATCH 2/3] updated examples README --- docs/api/connections.rst | 30 ++++++----------- docs/api/contact.rst | 51 +++++++++++++++++++++++++++++ docs/api/external_forces.rst | 14 ++++---- docs/api/surface.rst | 16 +++++++++ docs/index.rst | 2 ++ elastica/contact_forces.py | 63 ++++++++++++++++++++++++++++++++---- elastica/external_forces.py | 34 +------------------ elastica/interaction.py | 6 ---- elastica/surface/plane.py | 2 +- examples/README.md | 29 +++++++++-------- 10 files changed, 160 insertions(+), 87 deletions(-) create mode 100644 docs/api/contact.rst create mode 100644 docs/api/surface.rst diff --git a/docs/api/connections.rst b/docs/api/connections.rst index 42b8e3af..b616b4ca 100644 --- a/docs/api/connections.rst +++ b/docs/api/connections.rst @@ -1,4 +1,4 @@ -Connections / Contact / Joints +Connections / Joints ============================== .. _connections: @@ -8,44 +8,34 @@ Connections / Contact / Joints Description ----------- -.. rubric:: Available Connection/Contact/Joints +.. rubric:: Available Connections/Joints .. autosummary:: :nosignatures: FreeJoint - ExternalContact FixedJoint HingeJoint - SelfContact Compatibility ~~~~~~~~~~~~~ -=============================== ==== =========== -Connection / Contact / Joints Rod Rigid Body -=============================== ==== =========== +=============================== ==== =========== +Connection / Joints Rod Rigid Body +=============================== ==== =========== FreeJoint ✅ ❌ -ExternalContact ✅ ❌ FixedJoint ✅ ❌ HingeJoint ✅ ❌ -SelfContact ✅ ❌ -=============================== ==== =========== +=============================== ==== =========== -Built-in Connection / Contact / Joint +Built-in Connection / Joint ------------------------------------- .. autoclass:: FreeJoint - :special-members: __init__ - -.. autoclass:: ExternalContact - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques .. autoclass:: FixedJoint - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques .. autoclass:: HingeJoint - :special-members: __init__ - -.. autoclass:: SelfContact - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques diff --git a/docs/api/contact.rst b/docs/api/contact.rst new file mode 100644 index 00000000..e3b2b009 --- /dev/null +++ b/docs/api/contact.rst @@ -0,0 +1,51 @@ +Contact +============================== + +.. _contact: + +.. automodule:: elastica.contact_forces + +Description +----------- + +.. rubric:: Available Contact Classes + +.. autosummary:: + :nosignatures: + + NoContact + RodRodContact + RodCylinderContact + RodSelfContact + RodSphereContact + RodPlaneContact + RodPlaneContactWithAnisotropicFriction + CylinderPlaneContact + + +Built-in Contact Classes +------------------------------------- + +.. autoclass:: NoContact + :special-members: __init__,apply_contact + +.. autoclass:: RodRodContact + :special-members: __init__,apply_contact + +.. autoclass:: RodCylinderContact + :special-members: __init__,apply_contact + +.. autoclass:: RodSelfContact + :special-members: __init__,apply_contact + +.. autoclass:: RodSphereContact + :special-members: __init__,apply_contact + +.. autoclass:: RodPlaneContact + :special-members: __init__,apply_contact + +.. autoclass:: RodPlaneContactWithAnisotropicFriction + :special-members: __init__,apply_contact + +.. autoclass:: CylinderPlaneContact + :special-members: __init__,apply_contact diff --git a/docs/api/external_forces.rst b/docs/api/external_forces.rst index 8f84f66f..f34c0535 100644 --- a/docs/api/external_forces.rst +++ b/docs/api/external_forces.rst @@ -63,25 +63,25 @@ Built-in External Forces :noindex: .. autoclass:: NoForces - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques .. autoclass:: EndpointForces - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques .. autoclass:: GravityForces - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques .. autoclass:: UniformForces - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques .. autoclass:: UniformTorques - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques .. autoclass:: MuscleTorques - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques .. autoclass:: EndpointForcesSinusoidal - :special-members: __init__ + :special-members: __init__,apply_forces,apply_torques Built-in Environment Interactions --------------------------------- diff --git a/docs/api/surface.rst b/docs/api/surface.rst new file mode 100644 index 00000000..55d4615d --- /dev/null +++ b/docs/api/surface.rst @@ -0,0 +1,16 @@ +Surface +========== + ++----------+----+ +| type | | ++==========+====+ +| plane | | ++----------+----+ + +.. automodule:: elastica.surface.surface_base + :members: + :exclude-members: __weakref__ + +.. automodule:: elastica.surface.plane + :members: + :exclude-members: __weakref__ diff --git a/docs/index.rst b/docs/index.rst index 1bf57f21..59e639ad 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -54,9 +54,11 @@ If you are interested to contribute, please read `contribution-guide`_ first. api/rods api/rigidbody + api/surface api/constraints api/external_forces api/connections + api/contact api/callback api/time_steppers api/damping diff --git a/elastica/contact_forces.py b/elastica/contact_forces.py index 8a168032..8f9b0ab5 100644 --- a/elastica/contact_forces.py +++ b/elastica/contact_forces.py @@ -91,8 +91,8 @@ class RodRodContact(NoContact): Examples -------- - How to define contact between rod and rod. + >>> simulator.detect_contact_between(first_rod, second_rod).using( ... RodRodContact, ... k=1e4, @@ -148,6 +148,17 @@ def _check_systems_validity( ) def apply_contact(self, system_one: RodType, system_two: RodType) -> None: + """ + Apply contact forces and torques between RodType object and RodType object. + + Parameters + ---------- + system_one: object + Rod object. + system_two: object + Rod object. + + """ # First, check for a global AABB bounding box, and see whether that # intersects @@ -315,7 +326,10 @@ class RodSelfContact(NoContact): """ This class is modeling self contact of rod. + Examples + -------- How to define contact rod self contact. + >>> simulator.detect_contact_between(rod, rod).using( ... RodSelfContact, ... k=1e4, @@ -369,6 +383,17 @@ def _check_systems_validity( ) def apply_contact(self, system_one: RodType, system_two: RodType) -> None: + """ + Apply contact forces and torques between RodType object and itself. + + Parameters + ---------- + system_one: object + Rod object. + system_two: object + Rod object. + + """ _calculate_contact_forces_self_rod( system_one.position_collection[ ..., :-1 @@ -389,18 +414,22 @@ class RodSphereContact(NoContact): First system is always rod and second system is always sphere. In addition to the contact forces, user can define apply friction forces between rod and sphere that are in contact. For details on friction model refer to this [1]_. + Notes ----- The `velocity_damping_coefficient` is set to a high value (e.g. 1e4) to minimize slip and simulate stiction (static friction), while friction_coefficient corresponds to the Coulombic friction coefficient. + Examples -------- How to define contact between rod and sphere. + >>> simulator.detect_contact_between(rod, sphere).using( ... RodSphereContact, ... k=1e4, ... nu=10, ... ) + .. [1] Preclik T., Popa Constantin., Rude U., Regularizing a Time-Stepping Method for Rigid Multibody Dynamics, Multibody Dynamics 2011, ECCOMAS. URL: https://www10.cs.fau.de/publications/papers/2011/Preclik_Multibody_Ext_Abstr.pdf """ @@ -457,6 +486,17 @@ def _check_systems_validity( ) def apply_contact(self, system_one: RodType, system_two: SystemType) -> None: + """ + Apply contact forces and torques between RodType object and Sphere object. + + Parameters + ---------- + system_one: object + Rod object. + system_two: object + Sphere object. + + """ # First, check for a global AABB bounding box, and see whether that # intersects if _prune_using_aabbs_rod_sphere( @@ -507,7 +547,10 @@ class RodPlaneContact(NoContact): For more details regarding the contact module refer to Eqn 4.8 of Gazzola et al. RSoS (2018). - How to define contact between rod and plane. + Examples + -------- + How to define contact between rod and plane. + >>> simulator.detect_contact_between(rod, plane).using( ... RodPlaneContact, ... k=1e4, @@ -561,7 +604,7 @@ def _check_systems_validity( def apply_contact(self, system_one: RodType, system_two: SystemType) -> None: """ - In the case of contact with the plane, this function computes the plane reaction force on the element. + Apply contact forces and torques between RodType object and Plane object. Parameters ---------- @@ -593,7 +636,10 @@ class RodPlaneContactWithAnisotropicFriction(NoContact): For more details regarding the contact module refer to Eqn 4.8 of Gazzola et al. RSoS (2018). + Examples + -------- How to define contact between rod and plane. + >>> simulator.detect_contact_between(rod, plane).using( ... RodPlaneContactWithAnisotropicFriction, ... k=1e4, @@ -672,7 +718,7 @@ def _check_systems_validity( def apply_contact(self, system_one: RodType, system_two: SystemType) -> None: """ - In the case of contact with the plane, this function computes the plane reaction force on the element. + Apply contact forces and torques between RodType object and Plane object with anisotropic friction. Parameters ---------- @@ -717,7 +763,10 @@ class CylinderPlaneContact(NoContact): For more details regarding the contact module refer to Eqn 4.8 of Gazzola et al. RSoS (2018). - How to define contact between cylinder and plane. + Examples + -------- + How to define contact between cylinder and plane. + >>> simulator.detect_contact_between(cylinder, plane).using( ... CylinderPlaneContact, ... k=1e4, @@ -771,14 +820,14 @@ def _check_systems_validity( def apply_contact(self, system_one: Cylinder, system_two: SystemType): """ - This function computes the plane force response on the rigid body, in the + This function computes the plane force response on the cylinder, in the case of contact. Contact model given in Eqn 4.8 Gazzola et. al. RSoS 2018 paper is used. Parameters ---------- system_one: object - cylinder object. + Cylinder object. system_two: object Plane object. diff --git a/elastica/external_forces.py b/elastica/external_forces.py index 21c2b8eb..cb9c61e6 100644 --- a/elastica/external_forces.py +++ b/elastica/external_forces.py @@ -40,9 +40,6 @@ def apply_forces(self, system: SystemType, time: np.float64 = 0.0): time : float The time of simulation. - Returns - ------- - """ pass @@ -58,9 +55,6 @@ def apply_torques(self, system: SystemType, time: np.float64 = 0.0): time : float The time of simulation. - Returns - ------- - """ pass @@ -109,9 +103,6 @@ def compute_gravity_forces(acc_gravity, mass, external_forces): external_forces: numpy.ndarray 2D (dim, blocksize) array containing data with 'float' type. External force vector. - Returns - ------- - """ inplace_addition(external_forces, _batch_product_i_k_to_ik(acc_gravity, mass)) @@ -182,9 +173,6 @@ def compute_end_point_forces( ramp_up_time: float Applied forces are ramped up until ramp up time. - Returns - ------- - """ factor = min(1.0, time / ramp_up_time) external_forces[..., 0] += start_force * factor @@ -345,23 +333,7 @@ def __init__( self.my_spline = my_spline(self.s) else: - - def constant_function(input): - """ - Return array of ones same as the size of the input array. This - function is called when Beta spline function is not used. - - Parameters - ---------- - input - - Returns - ------- - - """ - return np.ones(input.shape) - - self.my_spline = constant_function(self.s) + self.my_spline = np.full_like(self.s, fill_value=1.0) def apply_torques(self, rod: RodType, time: np.float64 = 0.0): self.compute_muscle_torques( @@ -430,8 +402,6 @@ def inplace_addition(external_force_or_torque, force_or_torque): force_or_torque: numpy.ndarray 2D (dim, blocksize) array containing data with 'float' type. - Returns - ------- """ blocksize = force_or_torque.shape[1] @@ -454,8 +424,6 @@ def inplace_substraction(external_force_or_torque, force_or_torque): force_or_torque: numpy.ndarray 2D (dim, blocksize) array containing data with 'float' type. - Returns - ------- """ blocksize = force_or_torque.shape[1] diff --git a/elastica/interaction.py b/elastica/interaction.py index 737abf0b..95d4602e 100644 --- a/elastica/interaction.py +++ b/elastica/interaction.py @@ -240,9 +240,6 @@ def apply_forces(self, system, time=0.0): system time - Returns - ------- - """ _calculate_contact_forces_rod_plane_with_anisotropic_friction( self.plane_origin, @@ -505,9 +502,6 @@ def apply_forces(self, system, time=0.0): ---------- system - Returns - ------- - """ stokes_force = slender_body_forces( diff --git a/elastica/surface/plane.py b/elastica/surface/plane.py index ce2d96f3..a68a5be6 100644 --- a/elastica/surface/plane.py +++ b/elastica/surface/plane.py @@ -1,4 +1,4 @@ -__doc__ = """plane surface class""" +__doc__ = """""" from elastica.surface.surface_base import SurfaceBase import numpy as np diff --git a/examples/README.md b/examples/README.md index 489ea449..85dbc6c1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -26,17 +26,20 @@ Examples can serve as a starting template for customized usages. * __Purpose__: Physical convergence test of simple pendulum with flexible rod. * __Features__: CosseratRod, HingeBC, GravityForces * [ContinuumSnakeCase](./ContinuumSnakeCase) - * __Purpose__: Demonstrate simple case of modeling biological creature using PyElastica. The example use friction to create slithering snake, and optimize the speed using [CMA](https://github.com/CMA-ES/pycma). - * __Features__: CosseratRod, MuscleTorques, AnisotropicFrictionalPlane, Gravity, CMA Optimization - * [MuscularSnake](./MuscularSnake) - * __Purpose__: Example of [Parallel connection module](../elastica/experimental/connection_contact_joint/parallel_connection.py) and customized [Force module](./MuscularSnake/muscle_forces.py) to implement muscular snake. - * __Features__: MuscleForces(custom implemented) + * __Purpose__: Demonstrate simple case of modeling biological creature using PyElastica. The example uses friction to create slithering snake, and optimize the speed using [CMA](https://github.com/CMA-ES/pycma). + * __Features__: CosseratRod, MuscleTorques, RodPlaneContactWithAnisotropicFriction, Gravity, CMA Optimization +* [ContinuumSnakeWithLiftingWaveCase](./ContinuumSnakeWithLiftingWaveCase) + * __Purpose__: Demonstrate simple case of modeling biological creature using PyElastica. The example uses friction to create slithering snake with lift. + * __Features__: CosseratRod, MuscleTorquesLifting(custom implemented), SnakeRodPlaneContact(custom implemented), Gravity +* [MuscularSnake](./MuscularSnake) + * __Purpose__: Example of [Parallel connection module](../elastica/experimental/connection_contact_joint/parallel_connection.py) and customized [Force module](./MuscularSnake/muscle_forces.py) to implement muscular snake. + * __Features__: MuscleForces(custom implemented) * [ButterflyCase](./ButterflyCase) * __Purpose__: Demonstrate simple restoration with initial strain. * __Features__: CosseratRod * [FrictionValidationCases](./FrictionValidationCases) * __Purpose__: Physical validation of rolling and translational friction. - * __Features__: CosseratRod, UniformForces, AnisotropicFrictionalPlane + * __Features__: CosseratRod, UniformForces, RodPlaneContactWithAnisotropicFriction * [JointCases](./JointCases) * __Purpose__: Demonstrate various joint usage with Cosserat Rod. * __Features__: FreeJoint, FixedJoint, HingeJoint, OneEndFixedRod, EndpointForcesSinusoidal @@ -45,27 +48,27 @@ Examples can serve as a starting template for customized usages. * __Features__: Cylinder, Sphere * [RodRigidBodyContact](./RigidBodyCases/RodRigidBodyContact) * __Purpose__: Demonstrate contact between cylinder and rod, for different intial conditions. - * __Features__: Cylinder, CosseratRods, ExternalContact + * __Features__: Cylinder, CosseratRods, RodCylinderContact * [HelicalBucklingCase](./HelicalBucklingCase) * __Purpose__: Demonstrate helical buckling with extreme twisting boundary condition. * __Features__: HelicalBucklingBC * [ContinuumFlagellaCase](./ContinuumFlagellaCase) * __Purpose__: Demonstrate flagella modeling using PyElastica. * __Features__: SlenderBodyTheory, MuscleTorques, - * [MuscularFlagella](./MuscularFlagella) - * __Purpose__: Example of customizing [Joint module](./MuscularFlagella/connection_flagella.py) and [Force module](./MuscularFlagella/muscle_forces_flagella.py) to implement muscular flagella. - * __Features__: MuscleForces(custom implemented) +* [MuscularFlagella](./MuscularFlagella) + * __Purpose__: Example of customizing [Joint module](./MuscularFlagella/connection_flagella.py) and [Force module](./MuscularFlagella/muscle_forces_flagella.py) to implement muscular flagella. + * __Features__: MuscleForces(custom implemented) * [RodContactCase](./RodContactCase) * [RodRodContact](./RodContactCase/RodRodContact) * __Purpose__: Demonstrates contact between two rods, for different initial conditions. - * __Features__: CosseratRod, ExternalContact + * __Features__: CosseratRod, RodRodContact * [RodSelfContact](./RodContactCase/RodSelfContact) * [PlectonemesCase](./RodContactCase/RodSelfContact/PlectonemesCase) * __Purpose__: Demonstrates rod self contact with Plectoneme example, and how to use link-writhe-twist after simulation completed. - * __Features__: CosseratRod, SelonoidsBC, SelfContact, Link-Writhe-Twist + * __Features__: CosseratRod, SelonoidsBC, RodSelfContact, Link-Writhe-Twist * [SolenoidsCase](./RodContactCase/RodSelfContact/SolenoidsCase) * __Purpose__: Demonstrates rod self contact with Solenoid example, and how to use link-writhe-twist after simulation completed. - * __Features__: CosseratRod, SelonoidsBC, SelfContact, Link-Writhe-Twist + * __Features__: CosseratRod, SelonoidsBC, RodSelfContact, Link-Writhe-Twist * [BoundaryConditionsCases](./BoundaryConditionsCases) * __Purpose__: Demonstrate the usage of boundary conditions for constraining the movement of the system. * __Features__: GeneralConstraint, CosseratRod From 1dbcd3403ba5e5a6737947aa06612aa458db3a48 Mon Sep 17 00:00:00 2001 From: Ali-7800 <47090295+Ali-7800@users.noreply.github.com> Date: Thu, 15 Feb 2024 13:33:36 -0600 Subject: [PATCH 3/3] added CylinderPlaneContact class to elastica __init__.py --- elastica/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/elastica/__init__.py b/elastica/__init__.py index 76bd7888..e96e0057 100644 --- a/elastica/__init__.py +++ b/elastica/__init__.py @@ -51,6 +51,7 @@ RodSphereContact, RodPlaneContact, RodPlaneContactWithAnisotropicFriction, + CylinderPlaneContact, ) from elastica.callback_functions import CallBackBaseClass, ExportCallBack, MyCallBack from elastica.dissipation import (