Rods#

Base class for rods

class elastica.rod.rod_base.RodBase[source]#

Base class for all rods.

Notes

All new rod classes must be derived from this RodBase class.

Cosserat Rod#

On Nodes (+1)

On Elements (n_elements)

On Voronoi (-1)

Geometry

position

director, tangents
length, rest_length
radius
volume
dilatation
rest voronoi length
voronoi dilatation

Kinematics

velocity
acceleration
external forces
damping forces
angular velocity (omega)
angular acceleration (alpha)
mass second moment of inertia
+inverse
dilatation rates
external torques
damping torques

Elasticity

internal forces

shear matrix (modulus)
shear/stretch strain (sigma)
rest shear/stretch strain
internal torques
internal stress
bend matrix (modulus)
bend/twist strain (kappa)
rest bend/twist strain
internal couple

Material

mass

density
dissipation constant (force, torque)

Rod classes and implementation details

class elastica.rod.cosserat_rod.CosseratRod(n_elements, position, velocity, omega, acceleration, angular_acceleration, directors, radius, mass_second_moment_of_inertia, inv_mass_second_moment_of_inertia, shear_matrix, bend_matrix, density, volume, mass, internal_forces, internal_torques, external_forces, external_torques, lengths, rest_lengths, tangents, dilatation, dilatation_rate, voronoi_dilatation, rest_voronoi_lengths, sigma, kappa, rest_sigma, rest_kappa, internal_stress, internal_couple, ring_rod_flag)[source]#

Cosserat Rod class. This is the preferred class for rods because it is derived from some of the essential base classes.

Attributes:
n_elems: int

The number of elements of the rod.

position_collection: numpy.ndarray

2D (dim, n_nodes) array containing data with ‘float’ type. Array containing node position vectors.

velocity_collection: numpy.ndarray

2D (dim, n_nodes) array containing data with ‘float’ type. Array containing node velocity vectors.

acceleration_collection: numpy.ndarray

2D (dim, n_nodes) array containing data with ‘float’ type. Array containing node acceleration vectors.

omega_collection: numpy.ndarray

2D (dim, n_elems) array containing data with ‘float’ type. Array containing element angular velocity vectors.

alpha_collection: numpy.ndarray

2D (dim, n_elems) array containing data with ‘float’ type. Array contining element angular acceleration vectors.

director_collection: numpy.ndarray

3D (dim, dim, n_elems) array containing data with ‘float’ type. Array containing element director matrices.

rest_lengths: numpy.ndarray

1D (n_elems) array containing data with ‘float’ type. Rod element lengths at rest configuration.

density: numpy.ndarray

1D (n_elems) array containing data with ‘float’ type. Rod elements densities.

volume: numpy.ndarray

1D (n_elems) array containing data with ‘float’ type. Rod element volumes.

mass: numpy.ndarray

1D (n_nodes) array containing data with ‘float’ type. Rod node masses. Note that masses are stored on the nodes, not on elements.

mass_second_moment_of_inertia: numpy.ndarray

3D (dim, dim, n_elems) array containing data with ‘float’ type. Rod element mass second moment of interia.

inv_mass_second_moment_of_inertia: numpy.ndarray

3D (dim, dim, n_elems) array containing data with ‘float’ type. Rod element inverse mass moment of inertia.

rest_voronoi_lengths: numpy.ndarray

1D (n_voronoi) array containing data with ‘float’ type. Rod lengths on the voronoi domain at the rest configuration.

internal_forces: numpy.ndarray

2D (dim, n_nodes) array containing data with ‘float’ type. Rod node internal forces. Note that internal forces are stored on the node, not on elements.

internal_torques: numpy.ndarray

2D (dim, n_elems) array containing data with ‘float’ type. Rod element internal torques.

external_forces: numpy.ndarray

2D (dim, n_nodes) array containing data with ‘float’ type. External forces acting on rod nodes.

external_torques: numpy.ndarray

2D (dim, n_elems) array containing data with ‘float’ type. External torques acting on rod elements.

lengths: numpy.ndarray

1D (n_elems) array containing data with ‘float’ type. Rod element lengths.

tangents: numpy.ndarray

2D (dim, n_elems) array containing data with ‘float’ type. Rod element tangent vectors.

radius: numpy.ndarray

1D (n_elems) array containing data with ‘float’ type. Rod element radius.

dilatation: numpy.ndarray

1D (n_elems) array containing data with ‘float’ type. Rod element dilatation.

voronoi_dilatation: numpy.ndarray

1D (n_voronoi) array containing data with ‘float’ type. Rod dilatation on voronoi domain.

dilatation_rate: numpy.ndarray

1D (n_elems) array containing data with ‘float’ type. Rod element dilatation rates.

classmethod straight_rod(n_elements, start, direction, normal, base_length, base_radius, density, *, nu=None, youngs_modulus, **kwargs)[source]#

Cosserat rod constructor for straight-rod geometry.

Parameters:
n_elementsint

Number of element. Must be greater than 3. Generally recommended to start with 40-50, and adjust the resolution.

startNDArray[3, float]

Starting coordinate in 3D

directionNDArray[3, float]

Direction of the rod in 3D

normalNDArray[3, float]

Normal vector of the rod in 3D

base_lengthfloat

Total length of the rod

base_radiusfloat

Uniform radius of the rod

densityfloat

Density of the rod

nufloat

Damping coefficient for Rayleigh damping

youngs_modulusfloat

Young’s modulus

**kwargsdict, optional

The “position” and/or “directors” can be overrided by passing “position” and “directors” argument. Remember, the shape of the “position” is (3,n_elements+1) and the shape of the “directors” is (3,3,n_elements).

Returns:
CosseratRod

Notes

Since we expect the Cosserat Rod to simulate soft rod, Poisson’s ratio is set to 0.5 by default. It is possible to give additional argument “shear_modulus” or “poisson_ratio” to specify extra modulus.

classmethod ring_rod(n_elements, ring_center_position, direction, normal, base_length, base_radius, density, *, nu=None, youngs_modulus, **kwargs)[source]#

Cosserat rod constructor for straight-rod geometry.

Parameters:
n_elementsint

Number of element. Must be greater than 3. Generarally recommended to start with 40-50, and adjust the resolution.

ring_center_positionNDArray[3, float]

Center coordinate for ring rod in 3D

directionNDArray[3, float]

Direction of the rod in 3D

normalNDArray[3, float]

Normal vector of the rod in 3D

base_lengthfloat

Total length of the rod

base_radiusfloat

Uniform radius of the rod

densityfloat

Density of the rod

nufloat

Damping coefficient for Rayleigh damping

youngs_modulusfloat

Young’s modulus

**kwargsdict, optional

The “position” and/or “directors” can be overrided by passing “position” and “directors” argument. Remember, the shape of the “position” is (3,n_elements+1) and the shape of the “directors” is (3,3,n_elements).

Returns:
CosseratRod

Notes

Since we expect the Cosserat Rod to simulate soft rod, Poisson’s ratio is set to 0.5 by default. It is possible to give additional argument “shear_modulus” or “poisson_ratio” to specify extra modulus.

compute_translational_energy()[source]#

Compute total translational energy of the rod at the instance.

compute_rotational_energy()[source]#

Compute total rotational energy of the rod at the instance.

compute_velocity_center_of_mass()[source]#

Compute velocity center of mass of the rod at the instance.

compute_position_center_of_mass()[source]#

Compute position center of mass of the rod at the instance.

compute_bending_energy()[source]#

Compute total bending energy of the rod at the instance.

compute_shear_energy()[source]#

Compute total shear energy of the rod at the instance.

See Knot Theory (Mixin) for the detail.

Parameters:
type_of_additional_segmentstr

Determines the method to compute new segments (elements) added to the rod. Valid inputs are “next_tangent”, “end_to_end”, “net_tangent”, otherwise program uses the center line.

compute_twist()#

See Knot Theory (Mixin) for the detail.

compute_writhe(type_of_additional_segment='next_tangent')#

See Knot Theory (Mixin) for the detail.

Parameters:
type_of_additional_segmentstr

Determines the method to compute new segments (elements) added to the rod. Valid inputs are “next_tangent”, “end_to_end”, “net_tangent”, otherwise program uses the center line.

Knot Theory (Mixin)#

This script is for computing the link-writhe-twist (LWT) of a rod using the method from Klenin & Langowski 2000 paper. Algorithms are adapted from section S2 of Charles et. al. PRL 2019 paper.

Following example cases includes computing LWT quantities to study the bifurcation:

The details discussion is included in N Charles et. al. PRL (2019).

class elastica.rod.knot_theory.KnotTheoryCompatibleProtocol(*args, **kwargs)[source]#

Required properties to use KnotTheory mixin

class elastica.rod.knot_theory.KnotTheory[source]#

This mixin should be used in RodBase-derived class that satisfies KnotCompatibleProtocol. The theory behind this module is based on the method from Klenin & Langowski 2000 paper.

KnotTheory can be mixed with any rod-class based on RodBase:

class MyRod(RodBase, KnotTheory):
    def __init__(self):
        super().__init__()
rod = MyRod(...)

total_twist = rod.compute_twist()
total_link = rod.compute_link()

There are few alternative way of handling edge-condition in computing Link and Writhe. Here, we provide three methods: “next_tangent”, “end_to_end”, and “net_tangent”. The default type_of_additional_segment is set to “next_tangent.”

type_of_additional_segment

Description

next_tangent

Adds a two new point at the begining and end of the center line.
Distance of these points are given in segment_length.
Direction of these points are computed using the rod tangents at
the begining and end.

end_to_end

Adds a two new point at the begining and end of the center line.
Distance of these points are given in segment_length.
Direction of these points are computed using the rod node end
positions.

net_tangent

Adds a two new point at the begining and end of the center line.
Distance of these points are given in segment_length. Direction of
these points are point wise avarege of nodes at the first and
second half of the rod.
compute_twist()[source]#

See Knot Theory (Mixin) for the detail.

compute_writhe(type_of_additional_segment='next_tangent')[source]#

See Knot Theory (Mixin) for the detail.

Parameters:
type_of_additional_segmentstr

Determines the method to compute new segments (elements) added to the rod. Valid inputs are “next_tangent”, “end_to_end”, “net_tangent”, otherwise program uses the center line.

See Knot Theory (Mixin) for the detail.

Parameters:
type_of_additional_segmentstr

Determines the method to compute new segments (elements) added to the rod. Valid inputs are “next_tangent”, “end_to_end”, “net_tangent”, otherwise program uses the center line.

elastica.rod.knot_theory.compute_twist(center_line, normal_collection)[source]#

Compute the twist of a rod, using center_line and normal collection.

Methods used in this function is adapted from method 2a Klenin & Langowski 2000 paper.

Warning

If center line is straight, although the normals of each element is pointing different direction computed twist will be zero.

Typical runtime of this function is longer than simulation steps. While we provide a function to compute topological quantities at every timesteps, we highly recommend to compute LWT during the post-processing stage.:

import elastica
...
normal_collection = director_collection[:,0,...] # shape of director (time, 3, 3, n_elems)
elastica.compute_twist(
    center_line,                                 # shape (time, 3, n_nodes)
    normal_collection                            # shape (time, 3, n_elems)
)
Parameters:
center_linenumpy.ndarray

3D (time, 3, n_nodes) array containing data with ‘float’ type. Time history of rod node positions.

normal_collectionnumpy.ndarray

3D (time, 3, n_elems) array containing data with ‘float’ type. Time history of rod elements normal direction.

Returns:
total_twistnumpy.ndarray
local_twistnumpy.ndarray
elastica.rod.knot_theory.compute_writhe(center_line, segment_length, type_of_additional_segment)[source]#

This function computes the total writhe history of a rod.

Equations used are from method 1a from Klenin & Langowski 2000 paper.

Typical runtime of this function is longer than simulation steps. While we provide a function to compute topological quantities at every timesteps, we highly recommend to compute LWT during the post-processing stage.:

import elastica
...
elastica.compute_writhe(
    center_line,                               # shape (time, 3, n_nodes)
    segment_length,
    type_of_additional_segment="next_tangent"
)
Parameters:
center_linenumpy.ndarray

3D (time, 3, n_nodes) array containing data with ‘float’ type. Time history of rod node positions.

segment_lengthfloat

Length of added segments.

type_of_additional_segmentstr

Determines the method to compute new segments (elements) added to the rod. Valid inputs are “next_tangent”, “end_to_end”, “net_tangent”, otherwise program uses the center line.

Returns:
total_writhenumpy.ndarray

This function computes the total link history of a rod.

Equations used are from method 1a from Klenin & Langowski 2000 paper.

Typical runtime of this function is longer than simulation steps. While we provide a function to compute topological quantities at every timesteps, we highly recommend to compute LWT during the post-processing stage.:

import elastica
...
normal_collection = director_collection[:,0,...] # shape of director (time, 3, 3, n_elems)
elastica.compute_link(
    center_line,                                 # shape (time, 3, n_nodes)
    normal_collection,                           # shape (time 3, n_elems)
    radius,                                      # shape (time, n_elems)
    segment_length,
    type_of_additional_segment="next_tangent"
)
Parameters:
center_linenumpy.ndarray

3D (time, 3, n_nodes) array containing data with ‘float’ type. Time history of rod node positions.

normal_collectionnumpy.ndarray

3D (time, 3, n_elems) array containing data with ‘float’ type. Time history of rod elements normal direction.

radiusnumpy.ndarray

2D (time, n_elems) array containing data with ‘float’ type. Time history of rod element radius.

segment_lengthfloat

Length of added segments.

type_of_additional_segmentstr

Determines the method to compute new segments (elements) added to the rod. Valid inputs are “next_tangent”, “end_to_end”, “net_tangent”, otherwise program uses the center line.

Returns:
total_linknumpy.ndarray