1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Radu Serban
13 // =============================================================================
14
15 #include "chrono/physics/ChLinkSpringCB.h"
16
17 namespace chrono {
18
19 // Register into the object factory, to enable run-time dynamic creation and persistence
CH_FACTORY_REGISTER(ChLinkSpringCB)20 CH_FACTORY_REGISTER(ChLinkSpringCB)
21
22 ChLinkSpringCB::ChLinkSpringCB()
23 : m_force_fun(nullptr), m_ode_fun(nullptr), m_nstates(0), m_rest_length(0), m_force(0), m_variables(nullptr) {}
24
ChLinkSpringCB(const ChLinkSpringCB & other)25 ChLinkSpringCB::ChLinkSpringCB(const ChLinkSpringCB& other) : ChLinkMarkers(other) {
26 m_rest_length = other.m_rest_length;
27 m_force = other.m_force;
28 m_force_fun = other.m_force_fun;
29 m_ode_fun = other.m_ode_fun;
30 m_nstates = other.m_nstates;
31 m_states = other.m_states;
32 m_rhs = other.m_rhs;
33 if (other.m_variables) {
34 m_variables = new ChVariablesGenericDiagonalMass(other.m_variables->Get_ndof());
35 (*m_variables) = (*other.m_variables);
36 }
37 }
38
Clone() const39 ChLinkSpringCB* ChLinkSpringCB::Clone() const {
40 return new ChLinkSpringCB(*this);
41 }
42
~ChLinkSpringCB()43 ChLinkSpringCB::~ChLinkSpringCB() {
44 delete m_variables;
45 }
46
RegisterODE(ODE * functor)47 void ChLinkSpringCB::RegisterODE(ODE* functor) {
48 m_ode_fun = functor;
49 m_nstates = functor->GetNumStates();
50 m_states.resize(m_nstates);
51 m_rhs.resize(m_nstates);
52 functor->SetInitialConditions(m_states, this);
53 m_variables = new ChVariablesGenericDiagonalMass(m_nstates);
54 m_variables->GetMassDiagonal().Constant(m_nstates, 1);
55 }
56
Initialize(std::shared_ptr<ChBody> body1,std::shared_ptr<ChBody> body2,bool pos_are_relative,ChVector<> pos1,ChVector<> pos2,bool auto_rest_length,double rest_length)57 void ChLinkSpringCB::Initialize(std::shared_ptr<ChBody> body1,
58 std::shared_ptr<ChBody> body2,
59 bool pos_are_relative,
60 ChVector<> pos1,
61 ChVector<> pos2,
62 bool auto_rest_length,
63 double rest_length) {
64 // First, initialize as all links with markers.
65 // In this case, create the two markers also!.
66 ChLinkMarkers::Initialize(body1, body2, CSYSNORM);
67
68 if (pos_are_relative) {
69 marker1->Impose_Rel_Coord(ChCoordsys<>(pos1, QUNIT));
70 marker2->Impose_Rel_Coord(ChCoordsys<>(pos2, QUNIT));
71 } else {
72 marker1->Impose_Abs_Coord(ChCoordsys<>(pos1, QUNIT));
73 marker2->Impose_Abs_Coord(ChCoordsys<>(pos2, QUNIT));
74 }
75
76 ChVector<> AbsDist = marker1->GetAbsCoord().pos - marker2->GetAbsCoord().pos;
77 dist = AbsDist.Length();
78
79 m_rest_length = auto_rest_length ? dist : rest_length;
80 }
81
82 // -----------------------------------------------------------------------------
83
UpdateForces(double time)84 void ChLinkSpringCB::UpdateForces(double time) {
85 // Allow the base class to update itself (possibly adding its own forces)
86 ChLinkMarkers::UpdateForces(time);
87
88 // Invoke the provided functor to evaluate force
89 m_force = m_force_fun ? (*m_force_fun)(time, m_rest_length, dist, dist_dt, this) : 0;
90
91 // Add to existing force.
92 C_force += m_force * relM.pos.GetNormalized();
93 }
94
Update(double time,bool update_assets)95 void ChLinkSpringCB::Update(double time, bool update_assets) {
96 ChLinkMarkers::Update(time, update_assets);
97
98 // Evaluate ODE right-hand side at current state
99 if (m_ode_fun) {
100 m_ode_fun->CalculateRHS(time, m_states, m_rhs, this);
101 }
102 }
103
104 // -----------------------------------------------------------------------------
105
IntStateGather(const unsigned int off_x,ChState & x,const unsigned int off_v,ChStateDelta & v,double & T)106 void ChLinkSpringCB::IntStateGather(const unsigned int off_x, // offset in x state vector
107 ChState& x, // state vector, position part
108 const unsigned int off_v, // offset in v state vector
109 ChStateDelta& v, // state vector, speed part
110 double& T // time
111 ) {
112 if (!m_variables)
113 return;
114
115 x.segment(off_x, m_nstates).setZero();
116 v.segment(off_v, m_nstates) = m_states;
117 T = GetChTime();
118 }
119
IntStateScatter(const unsigned int off_x,const ChState & x,const unsigned int off_v,const ChStateDelta & v,const double T,bool full_update)120 void ChLinkSpringCB::IntStateScatter(const unsigned int off_x, // offset in x state vector
121 const ChState& x, // state vector, position part
122 const unsigned int off_v, // offset in v state vector
123 const ChStateDelta& v, // state vector, speed part
124 const double T, // time
125 bool full_update // perform complete update
126 ) {
127 Update(T, full_update);
128
129 if (!m_variables)
130 return;
131
132 m_states = v.segment(off_v, m_nstates);
133 }
134
IntStateGatherAcceleration(const unsigned int off_a,ChStateDelta & a)135 void ChLinkSpringCB::IntStateGatherAcceleration(const unsigned int off_a, ChStateDelta& a) {
136 if (!m_variables)
137 return;
138
139 a.segment(off_a, m_nstates) = m_rhs;
140 }
141
IntStateScatterAcceleration(const unsigned int off_a,const ChStateDelta & a)142 void ChLinkSpringCB::IntStateScatterAcceleration(const unsigned int off_a, const ChStateDelta& a) {
143 //// RADU: correct?!?
144 // do nothing here
145 }
146
IntLoadResidual_F(const unsigned int off,ChVectorDynamic<> & R,const double c)147 void ChLinkSpringCB::IntLoadResidual_F(const unsigned int off, // offset in R residual
148 ChVectorDynamic<>& R, // result: the R residual, R += c*F
149 const double c // a scaling factor
150 ) {
151 ChLinkMarkers::IntLoadResidual_F(off, R, c);
152
153 if (!m_variables)
154 return;
155
156 // add forcing term for internal states
157 R.segment(off, m_nstates) += c * m_rhs;
158 }
159
IntLoadResidual_Mv(const unsigned int off,ChVectorDynamic<> & R,const ChVectorDynamic<> & v,const double c)160 void ChLinkSpringCB::IntLoadResidual_Mv(const unsigned int off, // offset in R residual
161 ChVectorDynamic<>& R, // result: the R residual, R += c*M*v
162 const ChVectorDynamic<>& v, // the v vector
163 const double c // a scaling factor
164 ) {
165 if (!m_variables)
166 return;
167
168 R.segment(off, m_nstates) += c * v.segment(off, m_nstates);
169 }
170
IntToDescriptor(const unsigned int off_v,const ChStateDelta & v,const ChVectorDynamic<> & R,const unsigned int off_L,const ChVectorDynamic<> & L,const ChVectorDynamic<> & Qc)171 void ChLinkSpringCB::IntToDescriptor(const unsigned int off_v, // offset in v, R
172 const ChStateDelta& v,
173 const ChVectorDynamic<>& R,
174 const unsigned int off_L, // offset in L, Qc
175 const ChVectorDynamic<>& L,
176 const ChVectorDynamic<>& Qc) {
177 if (!m_variables)
178 return;
179
180 m_variables->Get_qb() = v.segment(off_v, m_nstates);
181 m_variables->Get_fb() = R.segment(off_v, m_nstates);
182 }
183
IntFromDescriptor(const unsigned int off_v,ChStateDelta & v,const unsigned int off_L,ChVectorDynamic<> & L)184 void ChLinkSpringCB::IntFromDescriptor(const unsigned int off_v, // offset in v
185 ChStateDelta& v,
186 const unsigned int off_L, // offset in L
187 ChVectorDynamic<>& L) {
188 if (!m_variables)
189 return;
190
191 v.segment(off_v, m_nstates) = m_variables->Get_qb();
192 }
193
194 // -----------------------------------------------------------------------------
195
InjectVariables(ChSystemDescriptor & mdescriptor)196 void ChLinkSpringCB::InjectVariables(ChSystemDescriptor& mdescriptor) {
197 ChLinkMarkers::InjectVariables(mdescriptor);
198
199 if (!m_variables)
200 return;
201
202 m_variables->SetDisabled(!IsActive());
203 mdescriptor.InsertVariables(m_variables);
204 }
205
VariablesFbReset()206 void ChLinkSpringCB::VariablesFbReset() {
207 if (!m_variables)
208 return;
209
210 m_variables->Get_fb().setZero();
211 }
212
VariablesFbLoadForces(double factor)213 void ChLinkSpringCB::VariablesFbLoadForces(double factor) {
214 if (!m_variables)
215 return;
216
217 m_variables->Get_fb() = m_rhs;
218 }
219
VariablesQbLoadSpeed()220 void ChLinkSpringCB::VariablesQbLoadSpeed() {
221 if (!m_variables)
222 return;
223
224 m_variables->Get_qb() = m_states;
225 }
226
VariablesQbSetSpeed(double step)227 void ChLinkSpringCB::VariablesQbSetSpeed(double step) {
228 if (!m_variables)
229 return;
230
231 m_states = m_variables->Get_qb();
232 }
233
VariablesFbIncrementMq()234 void ChLinkSpringCB::VariablesFbIncrementMq() {
235 if (!m_variables)
236 return;
237
238 m_variables->Compute_inc_Mb_v(m_variables->Get_fb(), m_variables->Get_qb());
239 }
240
VariablesQbIncrementPosition(double dt_step)241 void ChLinkSpringCB::VariablesQbIncrementPosition(double dt_step) {
242 //// RADU: correct?
243 // do nothing here
244 }
245
246 // -----------------------------------------------------------------------------
247
ArchiveOUT(ChArchiveOut & marchive)248 void ChLinkSpringCB::ArchiveOUT(ChArchiveOut& marchive) {
249 // version number
250 marchive.VersionWrite<ChLinkSpringCB>();
251
252 // serialize parent class
253 ChLinkMarkers::ArchiveOUT(marchive);
254
255 // serialize all member data:
256 marchive << CHNVP(m_rest_length);
257 }
258
ArchiveIN(ChArchiveIn & marchive)259 void ChLinkSpringCB::ArchiveIN(ChArchiveIn& marchive) {
260 // version number
261 /*int version =*/ marchive.VersionRead<ChLinkSpringCB>();
262
263 // deserialize parent class
264 ChLinkMarkers::ArchiveIN(marchive);
265
266 // deserialize all member data:
267 marchive >> CHNVP(m_rest_length);
268 }
269
270 } // end namespace chrono
271