1 /* Siconos is a program dedicated to modeling, simulation and control
2 * of non smooth dynamical systems.
3 *
4 * Copyright 2021 INRIA.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 #include "LagrangianDS.hpp"
19 #include "SiconosAlgebraProd.hpp" // for matrix-vector prod
20 #include "BlockVector.hpp"
21 #include "BlockMatrix.hpp"
22 // #define DEBUG_NOCOLOR
23 // #define DEBUG_STDOUT
24 // #define DEBUG_MESSAGES
25 #include "siconos_debug.h"
26 #include <iostream>
27
_init(SP::SiconosVector position,SP::SiconosVector velocity)28 void LagrangianDS::_init(SP::SiconosVector position, SP::SiconosVector velocity)
29 {
30 assert(_ndof > 0 && "lagrangian dynamical system dimension should be greater than 0.");
31
32 // Set initial conditions
33 _q0 = position;
34 _velocity0 = velocity;
35
36 // -- Memory allocation for vector and matrix members --
37 _q.resize(3);
38 _q[0].reset(new SiconosVector(*_q0));
39 _q[1].reset(new SiconosVector(*_velocity0));
40
41 /** \todo lazy Memory allocation */
42 _p.resize(3);
43 _p[1].reset(new SiconosVector(_ndof));
44
45 _zeroPlugin();
46 }
47
48
49 // Build from initial state only
LagrangianDS(SP::SiconosVector q0,SP::SiconosVector v0)50 LagrangianDS::LagrangianDS(SP::SiconosVector q0, SP::SiconosVector v0):
51 SecondOrderDS(2 * q0->size(), v0->size()),
52 _hasConstantFExt(true)
53 {
54 // Initial conditions
55 _init(q0, v0);
56 }
57
58 // From initial state and constant mass matrix, \f$ M\ddot q = p \f$
LagrangianDS(SP::SiconosVector q0,SP::SiconosVector v0,SP::SiconosMatrix newMass)59 LagrangianDS::LagrangianDS(SP::SiconosVector q0, SP::SiconosVector v0, SP::SiconosMatrix newMass):
60 SecondOrderDS(2 * q0->size(), v0->size()),
61 _hasConstantFExt(true)
62
63 {
64 _init(q0, v0);
65 // Mass matrix
66 _mass = newMass;
67 }
68
69
allocateMass()70 void LagrangianDS::allocateMass()
71 {
72 if(!_mass)
73 {
74 _mass.reset(new SimpleMatrix(_ndof, _ndof));
75 }
76
77 }
78
79
80 // From a set of data - Mass loaded from a plugin
81 // This constructor leads to the minimum Lagrangian System form: \f$ M(q)\ddot q = p \f$
LagrangianDS(SP::SiconosVector q0,SP::SiconosVector v0,const std::string & massName)82 LagrangianDS::LagrangianDS(SP::SiconosVector q0, SP::SiconosVector v0, const std::string& massName):
83 SecondOrderDS(2 * q0->size(), v0->size()),
84 _hasConstantFExt(true)
85 {
86 _init(q0, v0);
87 _hasConstantMass = false;
88 // Mass
89 allocateMass();
90 setComputeMassFunction(SSLH::getPluginName(massName), SSLH::getPluginFunctionName(massName));
91 }
92
_zeroPlugin()93 void LagrangianDS::_zeroPlugin()
94 {
95 _pluginMass.reset(new PluggedObject());
96 _pluginFInt.reset(new PluggedObject());
97 _pluginFExt.reset(new PluggedObject());
98 _pluginFGyr.reset(new PluggedObject());
99 _pluginJacqFInt.reset(new PluggedObject());
100 _pluginJacqDotFInt.reset(new PluggedObject());
101 _pluginJacqFGyr.reset(new PluggedObject());
102 _pluginJacqDotFGyr.reset(new PluggedObject());
103 }
104
initializeNonSmoothInput(unsigned int level)105 void LagrangianDS::initializeNonSmoothInput(unsigned int level)
106 {
107 if(!_p[level])
108 _p[level].reset(new SiconosVector(_ndof));
109 }
110
resetToInitialState()111 void LagrangianDS::resetToInitialState()
112 {
113 if(_q0)
114 {
115 *(_q[0]) = *_q0;
116 }
117 else
118 THROW_EXCEPTION("LagrangianDS::resetToInitialState - initial position _q0 is null");
119 if(_velocity0)
120 {
121 *(_q[1]) = *_velocity0;
122 }
123 else
124 THROW_EXCEPTION("LagrangianDS::resetToInitialState - initial velocity _velocity0 is null");
125 }
126
init_generalized_coordinates(unsigned int level)127 void LagrangianDS::init_generalized_coordinates(unsigned int level)
128 {
129 assert(level>1);
130 if(!_q[level])
131 _q[level].reset(new SiconosVector(_ndof));
132 }
133
134
init_inverse_mass()135 void LagrangianDS::init_inverse_mass()
136 {
137 if(_mass && !_inverseMass)
138 {
139 computeMass();
140 _inverseMass.reset(new SimpleMatrix(*_mass));
141 }
142 }
143
update_inverse_mass()144 void LagrangianDS::update_inverse_mass()
145 {
146 if(_mass && _inverseMass && !_hasConstantMass)
147 {
148 computeMass();
149 *_inverseMass = *_mass;
150 }
151 }
152
init_forces()153 void LagrangianDS::init_forces()
154 {
155 // Allocate memory for forces and its jacobians.void LagrangianDS::init_forces()
156 // Needed only for integrators with first-order formulation.
157 if(_fInt || _fExt || _fGyr)
158 {
159 if(!_forces)
160 _forces.reset(new SiconosVector(_ndof));
161 }
162
163 if(_fInt || _fGyr)
164 {
165 if(!_jacobianqForces)
166 _jacobianqForces.reset(new SimpleMatrix(_ndof, _ndof));
167 if(!_jacobianqDotForces)
168 _jacobianqDotForces.reset(new SimpleMatrix(_ndof, _ndof));
169 }
170 }
171
initRhs(double time)172 void LagrangianDS::initRhs(double time)
173 {
174 DEBUG_BEGIN("LagrangianDS::initRhs(double time)\n");
175 // dim
176 _n = 2 * _ndof;
177
178 // All links between DS and LagrangianDS class members are pointer links, which means
179 // that no useless memory is allocated when connection is established.
180 // One exception: zero and identity matrices, used to filled in M and jacobianfx.
181
182 // Initial conditions and state
183
184 // WARNING : this function is supposed to be called
185 // by the OneStepIntegrator, and maybe several times for the same DS
186 // if the system is involved in more than one interaction. So, we must check
187 // if p2 and q2 already exist to be sure that DSlink won't be lost.
188
189 _x0.reset(new SiconosVector(*_q0, *_velocity0));
190
191 _x[0].reset(new SiconosVector(*_q[0], *_q[1]));
192
193 if(!_q[2])
194 _q[2].reset(new SiconosVector(_ndof));
195
196 _x[1].reset(new SiconosVector(*_q[1], *_q[2]));
197
198 // Everything concerning rhs and its jacobian is handled in initRhs and computeXXX related functions.
199 _rhsMatrices.resize(numberOfRhsMatrices);
200
201 if(!_p[2])
202 _p[2].reset(new SiconosVector(_ndof));
203
204 init_forces();
205 init_inverse_mass();
206
207 computeRhs(time);
208
209 bool flag1 = false, flag2 = false;
210 if(_jacobianqForces)
211 {
212 // Solve MjacobianX(1,0) = jacobianFL[0]
213 computeJacobianqForces(time);
214
215 _rhsMatrices[jacobianXBloc10].reset(new SimpleMatrix(*_jacobianqForces));
216 _inverseMass->Solve(*_rhsMatrices[jacobianXBloc10]);
217 flag1 = true;
218 }
219
220 if(_jacobianqDotForces)
221 {
222 // Solve MjacobianX(1,1) = jacobianFL[1]
223 computeJacobianqDotForces(time);
224 _rhsMatrices[jacobianXBloc11].reset(new SimpleMatrix(*_jacobianqDotForces));
225 _inverseMass->Solve(*_rhsMatrices[jacobianXBloc11]);
226 flag2 = true;
227 }
228
229 if(!_rhsMatrices[zeroMatrix])
230 _rhsMatrices[zeroMatrix].reset(new SimpleMatrix(_ndof, _ndof, Siconos::ZERO));
231 if(!_rhsMatrices[idMatrix])
232 _rhsMatrices[idMatrix].reset(new SimpleMatrix(_ndof, _ndof, Siconos::IDENTITY));
233
234 if(flag1 && flag2)
235 _jacxRhs.reset(new BlockMatrix(_rhsMatrices[zeroMatrix], _rhsMatrices[idMatrix],
236 _rhsMatrices[jacobianXBloc10], _rhsMatrices[jacobianXBloc11]));
237 else if(flag1) // flag2 = false
238 _jacxRhs.reset(new BlockMatrix(_rhsMatrices[zeroMatrix], _rhsMatrices[idMatrix],
239 _rhsMatrices[jacobianXBloc10], _rhsMatrices[zeroMatrix]));
240 else if(flag2) // flag1 = false
241 _jacxRhs.reset(new BlockMatrix(_rhsMatrices[zeroMatrix], _rhsMatrices[idMatrix],
242 _rhsMatrices[zeroMatrix], _rhsMatrices[jacobianXBloc11]));
243 else
244 _jacxRhs.reset(new BlockMatrix(_rhsMatrices[zeroMatrix], _rhsMatrices[idMatrix],
245 _rhsMatrices[zeroMatrix], _rhsMatrices[zeroMatrix]));
246 DEBUG_EXPR(display(););
247 DEBUG_END("LagrangianDS::initRhs(double time)\n");
248 }
249
250 // --- GETTERS/SETTERS ---
251
setQ(const SiconosVector & newValue)252 void LagrangianDS::setQ(const SiconosVector& newValue)
253 {
254 if(newValue.size() != _ndof)
255 THROW_EXCEPTION("LagrangianDS - setQ: inconsistent input vector size ");
256
257 if(! _q[0])
258 _q[0].reset(new SiconosVector(newValue));
259 else
260 *_q[0] = newValue;
261 }
262
setQPtr(SP::SiconosVector newPtr)263 void LagrangianDS::setQPtr(SP::SiconosVector newPtr)
264 {
265 if(newPtr->size() != _ndof)
266 THROW_EXCEPTION("LagrangianDS - setQPtr: inconsistent input vector size ");
267 _q[0] = newPtr;
268
269 }
270
setQ0(const SiconosVector & newValue)271 void LagrangianDS::setQ0(const SiconosVector& newValue)
272 {
273 if(newValue.size() != _ndof)
274 THROW_EXCEPTION("LagrangianDS - setQ0: inconsistent input vector size ");
275
276 if(! _q0)
277 _q0.reset(new SiconosVector(newValue));
278 else
279 *_q0 = newValue;
280 }
281
setQ0Ptr(SP::SiconosVector newPtr)282 void LagrangianDS::setQ0Ptr(SP::SiconosVector newPtr)
283 {
284 if(newPtr->size() != _ndof)
285 THROW_EXCEPTION("LagrangianDS - setQ0Ptr: inconsistent input vector size ");
286 _q0 = newPtr;
287 }
288
setVelocity0(const SiconosVector & newValue)289 void LagrangianDS::setVelocity0(const SiconosVector& newValue)
290 {
291 if(newValue.size() != _ndof)
292 THROW_EXCEPTION("LagrangianDS - setVelocity0: inconsistent input vector size ");
293
294 if(! _velocity0)
295 _velocity0.reset(new SiconosVector(newValue));
296 else
297 *_velocity0 = newValue;
298 }
299
setVelocity(const SiconosVector & newValue)300 void LagrangianDS::setVelocity(const SiconosVector& newValue)
301 {
302 if(newValue.size() != _ndof)
303 THROW_EXCEPTION("LagrangianDS - setVelocity: inconsistent input vector size ");
304
305 if(! _q[1])
306 _q[1].reset(new SiconosVector(newValue));
307 else
308 *_q[1] = newValue;
309 }
310
setVelocityPtr(SP::SiconosVector newPtr)311 void LagrangianDS::setVelocityPtr(SP::SiconosVector newPtr)
312 {
313 if(newPtr->size() != _ndof)
314 THROW_EXCEPTION("LagrangianDS - setVelocityPtr: inconsistent input vector size ");
315 _q[1] = newPtr;
316 }
317
318
setVelocity0Ptr(SP::SiconosVector newPtr)319 void LagrangianDS::setVelocity0Ptr(SP::SiconosVector newPtr)
320 {
321 if(newPtr->size() != _ndof)
322 THROW_EXCEPTION("LagrangianDS - setVelocity0Ptr: inconsistent input vector size ");
323 _velocity0 = newPtr;
324 }
325
computeMass()326 void LagrangianDS::computeMass()
327 {
328 DEBUG_BEGIN("LagrangianDS::computeMass()\n");
329 DEBUG_EXPR(_q[0]->display());
330 computeMass(_q[0]);
331 DEBUG_EXPR(_mass->display());
332 DEBUG_END("LagrangianDS::computeMass()\n");
333 }
334
computeMass(SP::SiconosVector position)335 void LagrangianDS::computeMass(SP::SiconosVector position)
336 {
337 if(_mass && !_hasConstantMass && _pluginMass->fPtr)
338 {
339 ((FPtr7)_pluginMass->fPtr)(_ndof, &(*position)(0), &(*_mass)(0, 0), _z->size(), &(*_z)(0));
340 _mass->resetFactorizationFlags();
341 }
342 }
343
computeFInt(double time)344 void LagrangianDS::computeFInt(double time)
345 {
346 if(_fInt && _pluginFInt->fPtr)
347 ((FPtr6)_pluginFInt->fPtr)(time, _ndof, &(*_q[0])(0), &(*_q[1])(0), &(*_fInt)(0), _z->size(), &(*_z)(0));
348 }
computeFInt(double time,SP::SiconosVector position,SP::SiconosVector velocity)349 void LagrangianDS::computeFInt(double time, SP::SiconosVector position, SP::SiconosVector velocity)
350 {
351 if(_fInt && _pluginFInt->fPtr)
352 ((FPtr6)_pluginFInt->fPtr)(time, _ndof, &(*position)(0), &(*velocity)(0), &(*_fInt)(0), _z->size(), &(*_z)(0));
353 }
354
computeFExt(double time)355 void LagrangianDS::computeFExt(double time)
356 {
357 if(!_hasConstantFExt)
358 {
359 if(_fExt && _pluginFExt->fPtr)
360 ((VectorFunctionOfTime)_pluginFExt->fPtr)(time, _ndof, &(*_fExt)(0), _z->size(), &(*_z)(0));
361 }
362
363 }
computeFGyr()364 void LagrangianDS::computeFGyr()
365 {
366 if(_fGyr && _pluginFGyr->fPtr)
367 ((FPtr5)_pluginFGyr->fPtr)(_ndof, &(*_q[0])(0), &(*_q[1])(0), &(*_fGyr)(0), _z->size(), &(*_z)(0));
368 }
369
computeFGyr(SP::SiconosVector position,SP::SiconosVector velocity)370 void LagrangianDS::computeFGyr(SP::SiconosVector position, SP::SiconosVector velocity)
371 {
372 if(_fGyr && _pluginFGyr->fPtr)
373 ((FPtr5)_pluginFGyr->fPtr)(_ndof, &(*position)(0), &(*velocity)(0), &(*_fGyr)(0), _z->size(), &(*_z)(0));
374 }
375
376
computeJacobianFIntq(double time)377 void LagrangianDS::computeJacobianFIntq(double time)
378 {
379 DEBUG_BEGIN("LagrangianDS::computeJacobianFIntq()\n");
380 DEBUG_EXPR(_q[0]->display());
381 DEBUG_EXPR(_q[1]->display());
382 if(_jacobianFIntq&& _pluginJacqFInt->fPtr)
383 ((FPtr6)_pluginJacqFInt->fPtr)(time, _ndof, &(*_q[0])(0), &(*_q[1])(0), &(*_jacobianFIntq)(0, 0), _z->size(), &(*_z)(0));
384 DEBUG_EXPR(if(_jacobianFIntq) _jacobianFIntq->display(););
385 DEBUG_END("LagrangianDS::computeJacobianFIntq()\n");
386 }
computeJacobianFIntqDot(double time)387 void LagrangianDS::computeJacobianFIntqDot(double time)
388 {
389 DEBUG_BEGIN("LagrangianDS::computeJacobianFIntqDot()\n");
390 DEBUG_EXPR(_q[0]->display());
391 DEBUG_EXPR(_q[1]->display());
392 DEBUG_EXPR(_z->display());
393 if(_jacobianFIntqDot && _pluginJacqDotFInt->fPtr)
394 ((FPtr6)_pluginJacqDotFInt->fPtr)(time, _ndof, &(*_q[0])(0), &(*_q[1])(0), &(*_jacobianFIntqDot)(0, 0), _z->size(), &(*_z)(0));
395 DEBUG_EXPR(if(_jacobianFIntqDot) _jacobianFIntqDot->display(););
396 DEBUG_END("LagrangianDS::computeJacobianFIntqDot()\n");
397 }
398
399
computeJacobianFIntq(double time,SP::SiconosVector position,SP::SiconosVector velocity)400 void LagrangianDS::computeJacobianFIntq(double time, SP::SiconosVector position, SP::SiconosVector velocity)
401 {
402 DEBUG_BEGIN("LagrangianDS::computeJacobianFIntq()\n");
403 DEBUG_EXPR(position->display());
404 DEBUG_EXPR(velocity->display());
405 if(_jacobianFIntq && _pluginJacqFInt->fPtr)
406 ((FPtr6)_pluginJacqFInt->fPtr)(time, _ndof, &(*position)(0), &(*velocity)(0), &(*_jacobianFIntq)(0, 0), _z->size(), &(*_z)(0));
407 DEBUG_EXPR(if(_jacobianFIntq) _jacobianFIntq->display(););
408 DEBUG_END("LagrangianDS::computeJacobianFIntq()\n");
409 }
computeJacobianFIntqDot(double time,SP::SiconosVector position,SP::SiconosVector velocity)410 void LagrangianDS::computeJacobianFIntqDot(double time, SP::SiconosVector position, SP::SiconosVector velocity)
411 {
412 if(_jacobianFIntqDot && _pluginJacqDotFInt->fPtr)
413 ((FPtr6)_pluginJacqDotFInt->fPtr)(time, _ndof, &(*position)(0), &(*velocity)(0), &(*_jacobianFIntqDot)(0, 0), _z->size(), &(*_z)(0));
414 }
415
computeJacobianFGyrq()416 void LagrangianDS::computeJacobianFGyrq()
417 {
418 if(_pluginJacqFGyr->fPtr)
419 ((FPtr5)_pluginJacqFGyr->fPtr)(_ndof, &(*_q[0])(0), &(*_q[1])(0), &(*_jacobianFGyrq)(0, 0), _z->size(), &(*_z)(0));
420 }
computeJacobianFGyrqDot()421 void LagrangianDS::computeJacobianFGyrqDot()
422 {
423 if(_jacobianFGyrqDot && _pluginJacqDotFGyr->fPtr)
424 ((FPtr5)_pluginJacqDotFGyr->fPtr)(_ndof, &(*_q[0])(0), &(*_q[1])(0), &(*_jacobianFGyrqDot)(0, 0), _z->size(), &(*_z)(0));
425 }
426
computeJacobianFGyrq(SP::SiconosVector position,SP::SiconosVector velocity)427 void LagrangianDS::computeJacobianFGyrq(SP::SiconosVector position, SP::SiconosVector velocity)
428 {
429 if(_jacobianFGyrq && _pluginJacqFGyr->fPtr)
430 ((FPtr5)_pluginJacqFGyr->fPtr)(_ndof, &(*position)(0), &(*velocity)(0), &(*_jacobianFGyrq)(0, 0), _z->size(), &(*_z)(0));
431 }
432
computeJacobianFGyrqDot(SP::SiconosVector position,SP::SiconosVector velocity)433 void LagrangianDS::computeJacobianFGyrqDot(SP::SiconosVector position, SP::SiconosVector velocity)
434 {
435 if(_jacobianFGyrqDot && _pluginJacqDotFGyr->fPtr)
436 ((FPtr5)_pluginJacqDotFGyr->fPtr)(_ndof, &(*position)(0), &(*velocity)(0), &(*_jacobianFGyrqDot)(0, 0), _z->size(), &(*_z)(0));
437 }
438
computeRhs(double time)439 void LagrangianDS::computeRhs(double time)
440 {
441 DEBUG_BEGIN("LagrangianDS::computeRhs(double time)");
442 *_q[2] = *(_p[2]); // Warning: r/p update is done in Interactions/Relations
443
444 // if(_forces)
445 // {
446 computeForces(time, _q[0], _q[1]);
447 *_q[2] += *_forces;
448 DEBUG_EXPR(_forces->display(););
449 //# }
450
451 // Computes q[2] = inv(mass)*(fL+p) by solving Mq[2]=fL+p.
452 // -- Case 1: if mass is constant, then a copy of imass is LU-factorized during initialization and saved into _inverseMass
453 // -- Case 2: mass is not constant, we copy it into _inverseMass
454 // Then we proceed with PLUForwardBackward.
455 // mass and inv(mass) computation
456 if(_mass && !_hasConstantMass) // if it is necessary to re-compute mass, FInt ..., ie if they have not been compiled during the present time step
457 {
458 computeMass();
459 *_inverseMass = *_mass;
460 }
461
462 // if(mass->isPlugged()) : mass may be not plugged in LagrangianDS children
463 if(_inverseMass)
464 _inverseMass->Solve(*_q[2]);
465
466 _x[1]->setBlock(0, *_q[1]);
467 _x[1]->setBlock(_ndof, *_q[2]);
468 DEBUG_END("LagrangianDS::computeRhs(double time)");
469 }
470
computeJacobianRhsx(double time)471 void LagrangianDS::computeJacobianRhsx(double time)
472 {
473 if(!_hasConstantMass)
474 computeMass();
475
476 // if(mass->isPlugged()) : mass may b not plugged in LagrangianDS children
477
478 if(_jacobianqForces || _jacobianqDotForces)
479 {
480 if(!_hasConstantMass) // else inverseMass is already uptodate
481 *_inverseMass = *_mass;
482 }
483
484 if(_jacobianqForces)
485 {
486 /** \warning the Jacobian of the inverse of the mass matrix
487 * w.r.t q is not taken into account */
488
489 SP::SiconosMatrix bloc10 = _jacxRhs->block(1, 0);
490 computeJacobianqForces(time);
491 *bloc10 = *_jacobianqForces;
492 _inverseMass->Solve(*bloc10);
493 }
494
495 if(_jacobianqDotForces)
496 {
497 SP::SiconosMatrix bloc11 = _jacxRhs->block(1, 1);
498 computeJacobianqDotForces(time);
499 *bloc11 = *_jacobianqDotForces;
500 _inverseMass->Solve(*bloc11);
501 }
502 }
503
computeForces(double time,SP::SiconosVector position,SP::SiconosVector velocity)504 void LagrangianDS::computeForces(double time, SP::SiconosVector position, SP::SiconosVector velocity)
505 {
506 if(!_forces)
507 {
508 _forces.reset(new SiconosVector(_ndof));
509 }
510 else
511 _forces->zero();
512
513 // 1 - Computes the required function
514 computeFInt(time, position, velocity);
515 computeFExt(time);
516 computeFGyr(position, velocity);
517
518 // seems ok.
519 // if (_forces.use_count() == 1)
520 // {
521 // //if not that means that fL is already (pointer-)connected with
522 // // either fInt, FGyr OR fExt.
523 //_forces->zero();
524
525 if(_fInt)
526 *_forces -= *_fInt;
527
528 if(_fExt)
529 *_forces += *_fExt;
530
531 if(_fGyr)
532 *_forces -= *_fGyr;
533 // }
534
535 }
536
computeJacobianqForces(double time)537 void LagrangianDS::computeJacobianqForces(double time)
538 {
539 if(_jacobianqForces)
540 {
541 computeJacobianFIntq(time);
542 computeJacobianFGyrq();
543
544 // not true!
545 // if( jacobianFL[i].use_count() == 1 )
546 {
547 //if not that means that jacobianFL[i] is already (pointer-)connected with
548 // either jacobianFInt or jacobianFGyr
549 _jacobianqForces->zero();
550 if(_jacobianFIntq)
551 *_jacobianqForces -= *_jacobianFIntq;
552 if(_jacobianFGyrq)
553 *_jacobianqForces -= *_jacobianFGyrq;
554 }
555 }
556 //else nothing.
557 }
computeJacobianvForces(double time)558 void LagrangianDS::computeJacobianvForces(double time)
559 {
560 if(_jacobianqDotForces)
561 {
562 computeJacobianFIntqDot(time);
563 computeJacobianFGyrqDot();
564
565 // not true!
566 // if( jacobianFL[i].use_count() == 1 )
567 {
568 //if not that means that jacobianFL[i] is already (pointer-)connected with
569 // either jacobianFInt or jacobianFGyr
570 _jacobianqDotForces->zero();
571 if(_jacobianFIntqDot)
572 *_jacobianqDotForces -= *_jacobianFIntqDot;
573 if(_jacobianFGyrqDot)
574 *_jacobianqDotForces -= *_jacobianFGyrqDot;
575 }
576 }
577 //else nothing.
578 }
579 // void LagrangianDS::computeJacobianZFL( double time){
580 // THROW_EXCEPTION("LagrangianDS::computeJacobianZFL - not implemented");
581 // }
582
display(bool brief) const583 void LagrangianDS::display(bool brief) const
584 {
585 std::cout << "=====> Lagrangian System display (number: " << _number << ")." <<std::endl;
586 std::cout << "- _ndof : " << _ndof <<std::endl;
587 std::cout << "- q " <<std::endl;
588 if(_q[0]) _q[0]->display();
589 else std::cout << "-> nullptr" <<std::endl;
590 std::cout << "- q0 " <<std::endl;
591 if(_q0) _q0->display();
592 std::cout << "- velocity " <<std::endl;
593 if(_q[1]) _q[1]->display();
594 else std::cout << "-> nullptr" <<std::endl;
595 std::cout << "- acceleration " <<std::endl;
596 if(_q[2]) _q[2]->display();
597 else std::cout << "-> nullptr" <<std::endl;
598 std::cout << "- v0 " <<std::endl;
599 if(_velocity0) _velocity0->display();
600 else std::cout << "-> nullptr" <<std::endl;
601 std::cout << "- p[0] " <<std::endl;
602 if(_p[0]) _p[0]->display();
603 else std::cout << "-> nullptr" <<std::endl;
604 std::cout << "- p[1] " <<std::endl;
605 if(_p[1]) _p[1]->display();
606 else std::cout << "-> nullptr" <<std::endl;
607 std::cout << "- p[2] " <<std::endl;
608 if(_p[2]) _p[2]->display();
609 else std::cout << "-> nullptr" <<std::endl;
610
611 if(!brief)
612 {
613 std::cout << "- Mass " <<std::endl;
614 if(_mass) _mass ->display();
615 else std::cout << "-> nullptr" <<std::endl;
616
617 std::cout << "- Forces " <<std::endl;
618 if(_forces) _forces ->display();
619 else std::cout << "-> nullptr" <<std::endl;
620 std::cout << "- FInt " <<std::endl;
621 if(_fInt) _fInt ->display();
622 else std::cout << "-> nullptr" <<std::endl;
623
624 std::cout << "- jacobianqForces " <<std::endl;
625 if(_jacobianqForces) _jacobianqForces ->display();
626 else std::cout << "-> nullptr" <<std::endl;
627 std::cout << "- jacobianFIntq " <<std::endl;
628 if(_jacobianFIntq) _jacobianFIntq ->display();
629 else std::cout << "-> nullptr" <<std::endl;
630
631
632 std::cout << "- jacobianqDotForces " <<std::endl;
633 if(_jacobianqDotForces) _jacobianqDotForces ->display();
634 else std::cout << "-> nullptr" <<std::endl;
635
636 }
637
638
639 std::cout << "===================================== " <<std::endl;
640 }
641
642 // --- Functions for memory handling ---
initMemory(unsigned int steps)643 void LagrangianDS::initMemory(unsigned int steps)
644 {
645 DEBUG_PRINTF("LagrangianDS::initMemory(unsigned int steps) with steps = %i\n", steps);
646 if(steps == 0)
647 std::cout << "Warning : LagragianDS::initMemory with size equal to zero" <<std::endl;
648 else
649 {
650 _qMemory.setMemorySize(steps, _ndof);
651 _velocityMemory.setMemorySize(steps, _ndof);
652 _forcesMemory.setMemorySize(steps, _ndof);
653 _pMemory.resize(3);
654
655 //TODO : initMemory in graph + f(OSI/level)
656 for(unsigned int level=0; level<3; ++level)
657 {
658 if(_pMemory[level].size()==0)
659 _pMemory[level].setMemorySize(steps, _ndof);
660 }
661
662 //swapInMemory();
663 }
664 }
665
swapInMemory()666 void LagrangianDS::swapInMemory()
667 {
668 _qMemory.swap(*_q[0]);
669 _velocityMemory.swap(*_q[1]);
670 if(_forces)
671 _forcesMemory.swap(*_forces);
672
673 // initialization of the reaction force due to the non smooth law
674 // note: these are a no-op if either memory or vector is null
675 _pMemory[0].swap(_p[0]);
676 _pMemory[1].swap(_p[1]);
677 _pMemory[2].swap(_p[2]);
678 _xMemory.swap(_x[0]);
679 }
680
resetAllNonSmoothParts()681 void LagrangianDS::resetAllNonSmoothParts()
682 {
683 if(_p[0])
684 _p[0]->zero();
685 if(_p[1])
686 _p[1]->zero();
687 if(_p[2])
688 _p[2]->zero();
689 }
690
resetNonSmoothPart(unsigned int level)691 void LagrangianDS::resetNonSmoothPart(unsigned int level)
692 {
693 if(level < LEVELMAX)
694 if(_p[level])
695 _p[level]->zero();
696 }
697
computePostImpactVelocity()698 void LagrangianDS::computePostImpactVelocity()
699 {
700 // When this function is call, q[1] is supposed to be pre-impact velocity.
701 // We solve M(v+ - v-) = p - The result is saved in(place of) p[1].
702 DEBUG_BEGIN("LagrangianDS::computePostImpactV()\n");
703 SiconosVector tmp(*_p[1]);
704 if(_inverseMass)
705 _inverseMass->Solve(tmp);
706 *_q[1] += tmp; // v+ = v- + p
707 DEBUG_BEGIN("LagrangianDS::computePostImpactV() END \n");
708 }
allocateFExt()709 void LagrangianDS::allocateFExt()
710 {
711 if(!_fExt)
712 _fExt.reset(new SiconosVector(_ndof));
713 }
allocateFInt()714 void LagrangianDS::allocateFInt()
715 {
716 if(!_fInt)
717 _fInt.reset(new SiconosVector(_ndof));
718 }
719
setComputeFIntFunction(const std::string & pluginPath,const std::string & functionName)720 void LagrangianDS::setComputeFIntFunction(const std::string& pluginPath, const std::string& functionName)
721 {
722 _pluginFInt->setComputeFunction(pluginPath, functionName);
723 allocateFInt();
724 // Plugin::setFunction(&computeFIntPtr, pluginPath,functionName);
725 }
726
setComputeFIntFunction(FPtr6 fct)727 void LagrangianDS::setComputeFIntFunction(FPtr6 fct)
728 {
729 _pluginFInt->setComputeFunction((void*)fct);
730 allocateFInt();
731 // computeFIntPtr = fct;
732 }
733
734
735
736
737
setComputeFGyrFunction(const std::string & pluginPath,const std::string & functionName)738 void LagrangianDS::setComputeFGyrFunction(const std::string& pluginPath, const std::string& functionName)
739 {
740 _pluginFGyr->setComputeFunction(pluginPath, functionName);
741 if(!_fGyr)
742 _fGyr.reset(new SiconosVector(_ndof));
743 init_forces();
744 }
745
setComputeFGyrFunction(FPtr5 fct)746 void LagrangianDS::setComputeFGyrFunction(FPtr5 fct)
747 {
748 _pluginFGyr->setComputeFunction((void *)fct);
749 if(!_fGyr)
750 _fGyr.reset(new SiconosVector(_ndof));
751 init_forces();
752 }
753
allocateJacobianFIntq()754 void LagrangianDS::allocateJacobianFIntq()
755 {
756 if(!_jacobianFIntq)
757 _jacobianFIntq.reset(new SimpleMatrix(_ndof, _ndof));
758 }
759
setComputeJacobianFIntqFunction(const std::string & pluginPath,const std::string & functionName)760 void LagrangianDS::setComputeJacobianFIntqFunction(const std::string& pluginPath, const std::string& functionName)
761 {
762 _pluginJacqFInt->setComputeFunction(pluginPath, functionName);
763 allocateJacobianFIntq();
764 init_forces();
765 }
766
allocateJacobianFIntqDot()767 void LagrangianDS::allocateJacobianFIntqDot()
768 {
769 if(!_jacobianFIntqDot)
770 _jacobianFIntqDot.reset(new SimpleMatrix(_ndof, _ndof));
771 }
772
773
setComputeJacobianFIntqDotFunction(const std::string & pluginPath,const std::string & functionName)774 void LagrangianDS::setComputeJacobianFIntqDotFunction(const std::string& pluginPath, const std::string& functionName)
775 {
776 _pluginJacqDotFInt->setComputeFunction(pluginPath, functionName);
777 allocateJacobianFIntqDot();
778 init_forces();
779 }
780
setComputeJacobianFIntqFunction(FPtr6 fct)781 void LagrangianDS::setComputeJacobianFIntqFunction(FPtr6 fct)
782 {
783 _pluginJacqFInt->setComputeFunction((void *)fct);
784 allocateJacobianFIntq();
785 init_forces();
786 }
787
setComputeJacobianFIntqDotFunction(FPtr6 fct)788 void LagrangianDS::setComputeJacobianFIntqDotFunction(FPtr6 fct)
789 {
790 _pluginJacqDotFInt->setComputeFunction((void *)fct);
791 allocateJacobianFIntqDot();
792 init_forces();
793 }
794
setComputeJacobianFGyrqFunction(const std::string & pluginPath,const std::string & functionName)795 void LagrangianDS::setComputeJacobianFGyrqFunction(const std::string& pluginPath, const std::string& functionName)
796 {
797 _pluginJacqFGyr->setComputeFunction(pluginPath, functionName);
798 if(!_jacobianFGyrq)
799 _jacobianFGyrq.reset(new SimpleMatrix(_ndof, _ndof));
800 init_forces();
801 }
802
setComputeJacobianFGyrqDotFunction(const std::string & pluginPath,const std::string & functionName)803 void LagrangianDS::setComputeJacobianFGyrqDotFunction(const std::string& pluginPath, const std::string& functionName)
804 {
805 _pluginJacqDotFGyr->setComputeFunction(pluginPath, functionName);
806 if(!_jacobianFGyrqDot)
807 _jacobianFGyrqDot.reset(new SimpleMatrix(_ndof, _ndof));
808 init_forces();
809 }
810
setComputeJacobianFGyrqFunction(FPtr5 fct)811 void LagrangianDS::setComputeJacobianFGyrqFunction(FPtr5 fct)
812 {
813 _pluginJacqFGyr->setComputeFunction((void *)fct);
814 if(!_jacobianFGyrq)
815 _jacobianFGyrq.reset(new SimpleMatrix(_ndof, _ndof));
816 init_forces();
817 }
818
setComputeJacobianFGyrqDotFunction(FPtr5 fct)819 void LagrangianDS::setComputeJacobianFGyrqDotFunction(FPtr5 fct)
820 {
821 _pluginJacqDotFGyr->setComputeFunction((void *)fct);
822 if(!_jacobianFGyrqDot)
823 _jacobianFGyrqDot.reset(new SimpleMatrix(_ndof, _ndof));
824 }
825
computeKineticEnergy()826 double LagrangianDS::computeKineticEnergy()
827 {
828 DEBUG_BEGIN("NewtonEulerDS::computeKineticEnergy()\n");
829 SP::SiconosVector velo = velocity();
830 assert(velo);
831 DEBUG_EXPR(velo->display());
832
833 SP::SiconosVector tmp(new SiconosVector(*velo));
834 if(_mass)
835 prod(*_mass, *velo, *tmp, true);
836
837 double K =0.5*inner_prod(*tmp,*velo);
838
839 DEBUG_PRINTF("Kinetic Energy = %e\n", K);
840 DEBUG_END("LagrangianDS::computeKineticEnergy()\n");
841 return K;
842 }
843
844