-
Notifications
You must be signed in to change notification settings - Fork 107
/
spherical_joint.py
143 lines (124 loc) · 3.41 KB
/
spherical_joint.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
__doc__ = """Spherical(Free) joint example, for detailed explanation refer to Zhang et. al. Nature Comm.
methods section."""
import numpy as np
import elastica as ea
from examples.JointCases.joint_cases_postprocessing import (
plot_position,
plot_video,
plot_video_xy,
plot_video_xz,
)
class SphericalJointSimulator(
ea.BaseSystemCollection,
ea.Constraints,
ea.Connections,
ea.Forcing,
ea.Damping,
ea.CallBacks,
):
pass
spherical_joint_sim = SphericalJointSimulator()
# setting up test params
n_elem = 10
direction = np.array([0.0, 0.0, 1.0])
normal = np.array([0.0, 1.0, 0.0])
roll_direction = np.cross(direction, normal)
base_length = 0.2
base_radius = 0.007
base_area = np.pi * base_radius ** 2
density = 1750
E = 3e7
poisson_ratio = 0.5
shear_modulus = E / (poisson_ratio + 1.0)
start_rod_1 = np.zeros((3,))
start_rod_2 = start_rod_1 + direction * base_length
# Create rod 1
rod1 = ea.CosseratRod.straight_rod(
n_elem,
start_rod_1,
direction,
normal,
base_length,
base_radius,
density,
youngs_modulus=E,
shear_modulus=shear_modulus,
)
spherical_joint_sim.append(rod1)
# Create rod 2
rod2 = ea.CosseratRod.straight_rod(
n_elem,
start_rod_2,
direction,
normal,
base_length,
base_radius,
density,
youngs_modulus=E,
shear_modulus=shear_modulus,
)
spherical_joint_sim.append(rod2)
# Apply boundary conditions to rod1.
spherical_joint_sim.constrain(rod1).using(
ea.OneEndFixedBC, constrained_position_idx=(0,), constrained_director_idx=(0,)
)
# Connect rod 1 and rod 2
spherical_joint_sim.connect(
first_rod=rod1, second_rod=rod2, first_connect_idx=-1, second_connect_idx=0
).using(
ea.FreeJoint, k=1e5, nu=0
) # k=kg/s2 nu=kg/s 1e-2
# Add forces to rod2
spherical_joint_sim.add_forcing_to(rod2).using(
ea.EndpointForcesSinusoidal,
start_force_mag=0,
end_force_mag=5e-3,
ramp_up_time=0.2,
tangent_direction=direction,
normal_direction=normal,
)
# add damping
damping_constant = 4e-3
dt = 5e-5
spherical_joint_sim.dampen(rod1).using(
ea.AnalyticalLinearDamper,
damping_constant=damping_constant,
time_step=dt,
)
spherical_joint_sim.dampen(rod2).using(
ea.AnalyticalLinearDamper,
damping_constant=damping_constant,
time_step=dt,
)
pp_list_rod1 = ea.defaultdict(list)
pp_list_rod2 = ea.defaultdict(list)
spherical_joint_sim.collect_diagnostics(rod1).using(
ea.MyCallBack, step_skip=1000, callback_params=pp_list_rod1
)
spherical_joint_sim.collect_diagnostics(rod2).using(
ea.MyCallBack, step_skip=1000, callback_params=pp_list_rod2
)
spherical_joint_sim.finalize()
timestepper = ea.PositionVerlet()
# timestepper = PEFRL()
final_time = 10
dl = base_length / n_elem
total_steps = int(final_time / dt)
print("Total steps", total_steps)
ea.integrate(timestepper, spherical_joint_sim, final_time, total_steps)
PLOT_FIGURE = True
SAVE_FIGURE = False
PLOT_VIDEO = True
# plotting results
if PLOT_FIGURE:
filename = "spherical_joint_test_last_node_pos_xy.png"
plot_position(pp_list_rod1, pp_list_rod2, filename, SAVE_FIGURE)
if PLOT_VIDEO:
filename = "spherical_joint_test.mp4"
plot_video(pp_list_rod1, pp_list_rod2, video_name=filename, margin=0.2, fps=100)
plot_video_xy(
pp_list_rod1, pp_list_rod2, video_name=filename + "_xy.mp4", margin=0.2, fps=100
)
plot_video_xz(
pp_list_rod1, pp_list_rod2, video_name=filename + "_xz.mp4", margin=0.2, fps=100
)