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