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 "MoreauJeanGOSI.hpp"
19 #include "SiconosAlgebraProd.hpp"
20 #include "SiconosAlgebraScal.hpp"
21 //#include "SiconosVectorFriends.hpp"
22 #include "Simulation.hpp"
23 #include "NonSmoothDynamicalSystem.hpp"
24 #include "NewtonEulerDS.hpp"
25 #include "LagrangianLinearTIDS.hpp"
26 #include "NewtonEulerR.hpp"
27 #include "LagrangianRheonomousR.hpp"
28 #include "NewtonImpactNSL.hpp"
29 #include "MultipleImpactNSL.hpp"
30 #include "NewtonImpactFrictionNSL.hpp"
31 #include "NewtonImpactRollingFrictionNSL.hpp"
32 #include "TypeName.hpp"
33 
34 #include "OneStepNSProblem.hpp"
35 #include "BlockVector.hpp"
36 
37 
38 // #define DEBUG_STDOUT
39 // #define DEBUG_NOCOLOR
40 // #define DEBUG_MESSAGES
41 //#define DEBUG_WHERE_MESSAGES
42 #include "siconos_debug.h"
43 
44 
45 using namespace RELATION;
46 
47 /// for non-owned shared pointers (passing const SiconosVector into
48 /// functions that take SP::SiconosVector without copy -- warning
49 /// const abuse!)
null_deleter(const SiconosVector *)50 static void null_deleter(const SiconosVector *) {}
ptr(const T & a)51 template <typename T> static std::shared_ptr<T> ptr(const T& a)
52 {
53   return std::shared_ptr<SiconosVector>(&*(T*)&a, null_deleter);
54 }
55 
56 // --- constructor from a set of data ---
MoreauJeanGOSI(double theta,double gamma)57 MoreauJeanGOSI::MoreauJeanGOSI(double theta, double gamma):
58   OneStepIntegrator(OSI::MOREAUJEANGOSI), _useGammaForRelation(false), _explicitNewtonEulerDSOperators(false)
59 {
60   _levelMinForOutput= 0;
61   _levelMaxForOutput =1;
62   _levelMinForInput =1;
63   _levelMaxForInput =1;
64   _steps=1;
65   _theta = theta;
66   if(!std::isnan(gamma))
67   {
68     _gamma = gamma;
69     _useGamma = true;
70   }
71   else
72   {
73     _gamma = 1.0;
74     _useGamma = false;
75   }
76 }
initializeWorkVectorsForDS(double t,SP::DynamicalSystem ds)77 void MoreauJeanGOSI::initializeWorkVectorsForDS(double t, SP::DynamicalSystem ds)
78 {
79   // Get work buffers from the graph
80   VectorOfVectors& ds_work_vectors = *_initializeDSWorkVectors(ds);
81 
82   // Check dynamical system type
83   Type::Siconos dsType = Type::value(*ds);
84 
85   // Compute W (iteration matrix)
86   initializeIterationMatrixW(t, ds);
87   if(dsType == Type::LagrangianLinearTIDS || dsType == Type::LagrangianDS)
88   {
89     SP::LagrangianDS lds = std::static_pointer_cast<LagrangianDS> (ds);
90 
91     ds_work_vectors.resize(MoreauJeanGOSI::WORK_LENGTH);
92     ds_work_vectors[MoreauJeanGOSI::RESIDU_FREE].reset(new SiconosVector(lds->dimension()));
93     ds_work_vectors[MoreauJeanGOSI::FREE].reset(new SiconosVector(lds->dimension()));
94     ds_work_vectors[MoreauJeanGOSI::LOCAL_BUFFER].reset(new SiconosVector(lds->dimension()));
95 
96     lds->computeForces(t, lds->q(), lds->velocity());
97     lds->swapInMemory();
98   }
99   else if(dsType == Type::NewtonEulerDS)
100   {
101     SP::NewtonEulerDS neds = std::static_pointer_cast<NewtonEulerDS> (ds);
102     ds_work_vectors.resize(MoreauJeanGOSI::WORK_LENGTH);
103     ds_work_vectors[MoreauJeanGOSI::RESIDU_FREE].reset(new SiconosVector(neds->dimension()));
104     ds_work_vectors[MoreauJeanGOSI::FREE].reset(new SiconosVector(neds->dimension()));
105     //Compute a first value of the dotq  to store it in  _dotqMemory
106     SP::SiconosMatrix T = neds->T();
107     SP::SiconosVector dotq = neds->dotq();
108     SP::SiconosVector v = neds->twist();
109     prod(*T, *v, *dotq, true);
110 
111     //Compute a first value of the forces to store it in _forcesMemory
112     neds->computeForces(t, neds->q(), v);
113     neds->swapInMemory();
114   }
115 }
116 
initializeWorkVectorsForInteraction(Interaction & inter,InteractionProperties & interProp,DynamicalSystemsGraph & DSG)117 void MoreauJeanGOSI::initializeWorkVectorsForInteraction(Interaction &inter,
118     InteractionProperties& interProp,
119     DynamicalSystemsGraph & DSG)
120 {
121   SP::DynamicalSystem ds1= interProp.source;
122   SP::DynamicalSystem ds2= interProp.target;
123   assert(ds1);
124   assert(ds2);
125 
126   if(!interProp.workVectors)
127   {
128     interProp.workVectors.reset(new VectorOfVectors);
129     interProp.workVectors->resize(MoreauJeanGOSI::WORK_INTERACTION_LENGTH);
130   }
131 
132   if(!interProp.workBlockVectors)
133   {
134     interProp.workBlockVectors.reset(new VectorOfBlockVectors);
135     interProp.workBlockVectors->resize(MoreauJeanGOSI::BLOCK_WORK_LENGTH);
136   }
137 
138   VectorOfVectors& inter_work = *interProp.workVectors;
139   VectorOfBlockVectors& inter_block_work = *interProp.workBlockVectors;
140 
141 
142   if(!inter_work[MoreauJeanGOSI::OSNSP_RHS])
143     inter_work[MoreauJeanGOSI::OSNSP_RHS].reset(new SiconosVector(inter.dimension()));
144 
145   // Check if interations levels (i.e. y and lambda sizes) are compliant with the current osi.
146   _check_and_update_interaction_levels(inter);
147   // Initialize/allocate memory buffers in interaction.
148   inter.initializeMemory(_steps);
149 
150 
151   /* allocate and set work vectors for the osi */
152   unsigned int xfree = MoreauJeanGOSI::xfree;
153 
154   if(ds1 != ds2)
155   {
156     DEBUG_PRINT("ds1 != ds2\n");
157     if((!inter_block_work[xfree]) || (inter_block_work[xfree]->numberOfBlocks() !=2))
158       inter_block_work[xfree].reset(new BlockVector(2));
159   }
160   else
161   {
162     if((!inter_block_work[xfree]) || (inter_block_work[xfree]->numberOfBlocks() !=1))
163       inter_block_work[xfree].reset(new BlockVector(1));
164   }
165 
166   if(checkOSI(DSG.descriptor(ds1)))
167   {
168     DEBUG_PRINTF("ds1->number() %i is taken into account\n", ds1->number());
169     assert(DSG.properties(DSG.descriptor(ds1)).workVectors);
170     VectorOfVectors &workVds1 = *DSG.properties(DSG.descriptor(ds1)).workVectors;
171     inter_block_work[xfree]->setVectorPtr(0,workVds1[MoreauJeanGOSI::FREE]);
172   }
173   DEBUG_PRINTF("ds1->number() %i\n",ds1->number());
174   DEBUG_PRINTF("ds2->number() %i\n",ds2->number());
175 
176 
177   if(ds1 != ds2)
178   {
179     DEBUG_PRINT("ds1 != ds2\n");
180     if(checkOSI(DSG.descriptor(ds2)))
181     {
182       DEBUG_PRINTF("ds2->number() %i is taken into account\n",ds2->number());
183       assert(DSG.properties(DSG.descriptor(ds2)).workVectors);
184       VectorOfVectors &workVds2 = *DSG.properties(DSG.descriptor(ds2)).workVectors;
185       inter_block_work[xfree]->setVectorPtr(1,workVds2[MoreauJeanGOSI::FREE]);
186     }
187   }
188 
189 }
190 
initialize_nonsmooth_problems()191 void MoreauJeanGOSI::initialize_nonsmooth_problems()
192 {
193   SP::OneStepNSProblems  allOSNS  = _simulation->oneStepNSProblems();
194   ((*allOSNS)[SICONOS_OSNSP_TS_VELOCITY])->setIndexSetLevel(1);
195   ((*allOSNS)[SICONOS_OSNSP_TS_VELOCITY])->setInputOutputLevel(1);
196   //  ((*allOSNS)[SICONOS_OSNSP_TS_VELOCITY])->initialize(_simulation);
197 }
198 
initializeIterationMatrixW(double t,SP::DynamicalSystem ds)199 void MoreauJeanGOSI::initializeIterationMatrixW(double t, SP::DynamicalSystem ds)
200 {
201   DEBUG_PRINT("MoreauJeanGOSI::initializeIterationMatrixW starts\n");
202   // This function:
203   // - allocate memory for the matrix W
204   // - update its content for the current (initial) state of the dynamical system, depending on its type.
205 
206   if(!ds)
207     THROW_EXCEPTION("MoreauJeanGOSI::initializeIterationMatrixW(t, ds, dsv) - ds == nullptr or dsv == nullptr");
208 
209   if(!(checkOSI(_dynamicalSystemsGraph->descriptor(ds))))
210     THROW_EXCEPTION("MoreauJeanOSI::initializeIterationMatrixW(t,ds) - ds does not belong to the OSI.");
211 
212   const DynamicalSystemsGraph::VDescriptor& dsv = _dynamicalSystemsGraph->descriptor(ds);
213 
214   if(_dynamicalSystemsGraph->properties(dsv).W)
215     THROW_EXCEPTION("MoreauJeanGOSI::initializeIterationMatrixW(t,ds) - W(ds) is already in the map and has been initialized.");
216 
217   double h = _simulation->timeStep();
218   Type::Siconos dsType = Type::value(*ds);
219   unsigned int sizeW = ds->dimension();
220   if(dsType == Type::LagrangianDS)
221   {
222     SP::LagrangianDS d = std::static_pointer_cast<LagrangianDS> (ds);
223     if(d->mass())
224     {
225       d->computeMass(d->q());
226       _dynamicalSystemsGraph->properties(dsv).W.reset(new SimpleMatrix(*d->mass())); //*W = *d->mass();
227     }
228     else
229     {
230       _dynamicalSystemsGraph->properties(dsv).W.reset(new SimpleMatrix(sizeW, sizeW));
231       _dynamicalSystemsGraph->properties(dsv).W->eye();
232     }
233     // Compute the W matrix
234     computeW(t, ds, *_dynamicalSystemsGraph->properties(dsv).W);
235     // WBoundaryConditions initialization
236     if(d->boundaryConditions())
237       initializeIterationMatrixWBoundaryConditions(d);
238   }
239   // 2 - Lagrangian linear systems
240   else if(dsType == Type::LagrangianLinearTIDS)
241   {
242     SP::LagrangianLinearTIDS d = std::static_pointer_cast<LagrangianLinearTIDS> (ds);
243     _dynamicalSystemsGraph->properties(dsv).W.reset(new SimpleMatrix(*d->mass()));
244     SiconosMatrix& W = *_dynamicalSystemsGraph->properties(dsv).W;
245 
246     SP::SiconosMatrix K = d->K();
247     SP::SiconosMatrix C = d->C();
248 
249     if(C)
250       scal(h * _theta, *C, W, false); // W += h*_theta *C
251     if(K)
252       scal(h * h * _theta * _theta, *K, W, false); // W = h*h*_theta*_theta*K
253 
254     // WBoundaryConditions initialization
255     if(d->boundaryConditions())
256       initializeIterationMatrixWBoundaryConditions(d);
257   }
258 
259   // === ===
260   else if(dsType == Type::NewtonEulerDS)
261   {
262     SP::NewtonEulerDS d = std::static_pointer_cast<NewtonEulerDS> (ds);
263     _dynamicalSystemsGraph->properties(dsv).W.reset(new SimpleMatrix(*d->mass()));
264 
265     computeW(t,ds, *_dynamicalSystemsGraph->properties(dsv).W);
266     // WBoundaryConditions initialization
267     if(d->boundaryConditions())
268       initializeIterationMatrixWBoundaryConditions(d);
269 
270   }
271   else THROW_EXCEPTION("MoreauJeanGOSI::initializeIterationMatrixW - not yet implemented for Dynamical system of type : " + Type::name(*ds));
272 
273   // Remark: W is not LU-factorized nor inversed here.
274   // Function PLUForwardBackward will do that if required.
275   DEBUG_PRINT("MoreauJeanGOSI::initializeIterationMatrixW ends\n");
276 
277 
278 }
279 
280 
initializeIterationMatrixWBoundaryConditions(SP::DynamicalSystem ds)281 void MoreauJeanGOSI::initializeIterationMatrixWBoundaryConditions(SP::DynamicalSystem ds)
282 {
283   // This function:
284   // - allocate memory for a matrix WBoundaryConditions
285   // - insert this matrix into WBoundaryConditionsMap with ds as a key
286 
287   DEBUG_PRINT("MoreauJeanGOSI::initializeIterationMatrixWBoundaryConditions(SP::DynamicalSystem ds) starts\n");
288   if(!ds)
289     THROW_EXCEPTION("MoreauJeanGOSI::initializeIterationMatrixWBoundaryConditions(t,ds) - ds == nullptr");
290 
291   if(!(checkOSI(_dynamicalSystemsGraph->descriptor(ds))))
292     THROW_EXCEPTION("MoreauJeanGOSI::initializeIterationMatrixWBoundaryConditions(t,ds) - ds does not belong to the OSI.");
293 
294   Type::Siconos dsType = Type::value(*ds);
295   unsigned int dsN = ds->number();
296 
297   if(dsType == Type::LagrangianLinearTIDS || dsType == Type::LagrangianDS || dsType == Type::NewtonEulerDS)
298   {
299     if(_WBoundaryConditionsMap.find(dsN) != _WBoundaryConditionsMap.end())
300       THROW_EXCEPTION("MoreauJeanGOSI::initializeIterationMatrixWBoundaryConditions(t,ds) - WBoundaryConditions(ds) is already in the map and has been initialized.");
301 
302     // Memory allocation for WBoundaryConditions
303     unsigned int sizeWBoundaryConditions = ds->dimension(); // n for first order systems, ndof for lagrangian.
304 
305     SP::BoundaryCondition bc;
306     if(dsType == Type::LagrangianDS || dsType == Type::LagrangianLinearTIDS)
307     {
308       SP::LagrangianDS d = std::static_pointer_cast<LagrangianDS> (ds);
309       bc = d->boundaryConditions();
310     }
311     else if(dsType == Type::NewtonEulerDS)
312     {
313       SP::NewtonEulerDS d = std::static_pointer_cast<NewtonEulerDS> (ds);
314       bc = d->boundaryConditions();
315     }
316     unsigned int numberBoundaryConditions = bc->velocityIndices()->size();
317     _WBoundaryConditionsMap[dsN].reset(new SimpleMatrix(sizeWBoundaryConditions, numberBoundaryConditions));
318     computeWBoundaryConditions(ds);
319   }
320   else
321     THROW_EXCEPTION("MoreauJeanGOSI::initializeIterationMatrixWBoundaryConditions - not yet implemented for Dynamical system of type :" +  Type::name(*ds));
322   DEBUG_PRINT("MoreauJeanGOSI::initializeIterationMatrixWBoundaryConditions(SP::DynamicalSystem ds) ends \n");
323 }
324 
325 
computeWBoundaryConditions(SP::DynamicalSystem ds)326 void MoreauJeanGOSI::computeWBoundaryConditions(SP::DynamicalSystem ds)
327 {
328   // Compute WBoundaryConditions matrix of the Dynamical System ds, at
329   // time t and for the current ds state.
330 
331   // When this function is called, WBoundaryConditionsMap[ds] is
332   // supposed to exist and not to be null Memory allocation has been
333   // done during initializeIterationMatrixWBoundaryConditions.
334 
335   assert(ds &&
336          "MoreauJeanGOSI::computeWBoundaryConditions(t,ds) - ds == nullptr");
337 
338   Type::Siconos dsType = Type::value(*ds);
339   unsigned int dsN = ds->number();
340   if(dsType == Type::LagrangianLinearTIDS || dsType == Type::LagrangianDS ||  dsType == Type::NewtonEulerDS)
341   {
342     assert((_WBoundaryConditionsMap.find(dsN) != _WBoundaryConditionsMap.end()) &&
343            "MoreauJeanGOSI::computeW(t,ds) - W(ds) does not exists. Maybe you forget to initialize the osi?");
344 
345     SP::SimpleMatrix WBoundaryConditions = _WBoundaryConditionsMap[dsN];
346 
347     SP::SiconosVector columntmp(new SiconosVector(ds->dimension()));
348 
349     int columnindex = 0;
350 
351     std::vector<unsigned int>::iterator itindex;
352 
353     SP::BoundaryCondition bc;
354     if(dsType == Type::LagrangianDS || dsType == Type::LagrangianLinearTIDS)
355     {
356       LagrangianDS& d = static_cast<LagrangianDS&>(*ds);
357       bc = d.boundaryConditions();
358     }
359     else if(dsType == Type::NewtonEulerDS)
360     {
361       NewtonEulerDS& d = static_cast<NewtonEulerDS&>(*ds);
362       bc = d.boundaryConditions();
363     }
364     SP::SiconosMatrix W = _dynamicalSystemsGraph->properties(_dynamicalSystemsGraph->descriptor(ds)).W;
365 
366     for(itindex = bc->velocityIndices()->begin() ;
367         itindex != bc->velocityIndices()->end();
368         ++itindex)
369     {
370 
371       W->getCol(*itindex, *columntmp);
372       /*\warning we assume that W is symmetric in the Lagrangian case
373         we store only the column and not the row */
374 
375       WBoundaryConditions->setCol(columnindex, *columntmp);
376       double diag = (*columntmp)(*itindex);
377       columntmp->zero();
378       (*columntmp)(*itindex) = diag;
379 
380       W->setCol(*itindex, *columntmp);
381       W->setRow(*itindex, *columntmp);
382 
383 
384       columnindex ++;
385     }
386     DEBUG_EXPR(W->display());
387   }
388   else
389     THROW_EXCEPTION("MoreauJeanGOSI::computeWBoundaryConditions - not yet implemented for Dynamical system type : " +  Type::name(*ds));
390 }
391 
392 
computeW(double t,SP::DynamicalSystem ds,SiconosMatrix & W)393 void MoreauJeanGOSI::computeW(double t, SP::DynamicalSystem ds, SiconosMatrix& W)
394 {
395   // Compute W matrix of the Dynamical System ds, at time t and for the current ds state.
396   DEBUG_PRINT("MoreauJeanGOSI::computeW starts\n");
397 
398   assert(ds &&
399          "MoreauJeanGOSI::computeW(t,ds) - ds == nullptr");
400 
401   double h = _simulation->timeStep();
402   Type::Siconos dsType = Type::value(*ds);
403 
404   if(dsType == Type::LagrangianLinearTIDS)
405   {
406     // Nothing: W does not depend on time.
407   }
408   else if(dsType == Type::LagrangianDS)
409   {
410 
411     SP::LagrangianDS d = std::static_pointer_cast<LagrangianDS> (ds);
412     SP::SiconosMatrix K = d->jacobianqForces(); // jacobian according to q
413     SP::SiconosMatrix C = d->jacobianvForces(); // jacobian according to velocity
414 
415     if(d->mass())
416     {
417       d->computeMass(d->q());
418       W = *d->mass();
419     }
420     else
421       W.zero();
422 
423     if(C)
424     {
425       d->computeJacobianqDotForces(t);
426       scal(-h * _theta, *C, W, false); // W -= h*_theta*C
427     }
428 
429     if(K)
430     {
431       d->computeJacobianqForces(t);
432       scal(-h * h * _theta * _theta, *K, W, false); //*W -= h*h*_theta*_theta**K;
433     }
434   }
435   // === ===
436   else if(dsType == Type::NewtonEulerDS)
437   {
438     SP::NewtonEulerDS d = std::static_pointer_cast<NewtonEulerDS> (ds);
439     W = *(d->mass());
440 
441     SP::SiconosMatrix K = d->jacobianqForces(); // jacobian according to q
442     SP::SiconosMatrix C = d->jacobianvForces(); // jacobian according to velocity
443 
444     if(C)
445     {
446       d->computeJacobianvForces(t);
447       scal(-h * _theta, *C, W, false); // W -= h*_theta*C
448     }
449     if(K)
450     {
451       d->computeJacobianqForces(t);
452       SP::SiconosMatrix T = d->T();
453       DEBUG_EXPR(T->display(););
454       DEBUG_EXPR(K->display(););
455       SP::SimpleMatrix  buffer(new SimpleMatrix(*(d->mass())));
456       prod(*K, *T, *buffer, true);
457       scal(-h * h * _theta * _theta, *buffer, W, false);
458       //*W -= h*h*_theta*_theta**K;
459     }
460   }
461   else THROW_EXCEPTION("MoreauJeanGOSI::computeW - not yet implemented for Dynamical system of type : " +Type::name(*ds));
462   DEBUG_PRINT("MoreauJeanGOSI::computeW ends\n");
463   // Remark: W is not LU-factorized here.
464   // Function PLUForwardBackward will do that if required.
465 }
466 
computeInitialNewtonState()467 void MoreauJeanGOSI::computeInitialNewtonState()
468 {
469   DEBUG_PRINT("MoreauJeanGOSI::computeInitialNewtonState() starts\n");
470   // Compute the position value giving the initial velocity.
471   // The goal of to save one newton iteration for nearly linear system
472   DynamicalSystemsGraph::VIterator dsi, dsend;
473   for(std::tie(dsi, dsend) = _dynamicalSystemsGraph->vertices(); dsi != dsend; ++dsi)
474   {
475     if(!checkOSI(dsi)) continue;
476     DynamicalSystem &ds = *_dynamicalSystemsGraph->bundle(*dsi);
477 
478     if(_explicitNewtonEulerDSOperators)
479     {
480       if(Type::value(ds) == Type::NewtonEulerDS)
481       {
482         // The goal is to update T() one time at the beginning of the Newton Loop
483         // We want to be explicit on this function since we do not compute their Jacobians.
484         NewtonEulerDS& d = static_cast<NewtonEulerDS&>(ds);
485         const SiconosVector& qold = d.qMemory().getSiconosVector(0);
486         //SP::SiconosVector q = d.q();
487         computeT(ptr(qold),d.T());
488       }
489     }
490     // The goal is to converge in one iteration of the system is almost linear
491     // we start the Newton loop q = q0+hv0
492     updatePosition(ds);
493 
494 
495   }
496   DEBUG_PRINT("MoreauJeanGOSI::computeInitialNewtonState() ends\n");
497 }
498 
499 
500 
computeResidu()501 double MoreauJeanGOSI::computeResidu()
502 {
503   DEBUG_PRINT("\nMoreauJeanGOSI::computeResidu(), start\n");
504   // This function is used to compute the residu for each "MoreauJeanGOSI-discretized" dynamical system.
505   // It then computes the norm of each of them and finally return the maximum
506   // value for those norms.
507   //
508   // The state values used are those saved in the DS, ie the last computed ones.
509   //  $\mathcal R(x,r) = x - x_{k} -h\theta f( x , t_{k+1}) - h(1-\theta)f(x_k,t_k) - h r$
510   //  $\mathcal R_{free}(x,r) = x - x_{k} -h\theta f( x , t_{k+1}) - h(1-\theta)f(x_k,t_k) $
511 
512   double t = _simulation->nextTime(); // End of the time step
513   double told = _simulation->startingTime(); // Beginning of the time step
514   double h = t - told; // time step length
515 
516   DEBUG_PRINTF("nextTime %f\n", t);
517   DEBUG_PRINTF("startingTime %f\n", told);
518   DEBUG_PRINTF("time step size %f\n", h);
519 
520 
521   // Operators computed at told have index i, and (i+1) at t.
522 
523   // Iteration through the set of Dynamical Systems.
524   //
525   SP::DynamicalSystem ds; // Current Dynamical System.
526   Type::Siconos dsType ; // Type of the current DS.
527 
528   double maxResidu = 0;
529   double normResidu = maxResidu;
530 
531   DynamicalSystemsGraph::VIterator dsi, dsend;
532   for(std::tie(dsi, dsend) = _dynamicalSystemsGraph->vertices(); dsi != dsend; ++dsi)
533   {
534     if(!checkOSI(dsi)) continue;
535     ds = _dynamicalSystemsGraph->bundle(*dsi);
536     VectorOfVectors& ds_work_vectors = *_dynamicalSystemsGraph->properties(*dsi).workVectors;
537 
538     dsType = Type::value(*ds); // Its type
539 
540     // 3 - Lagrangian Non Linear Systems
541     if(dsType == Type::LagrangianDS)
542     {
543       DEBUG_PRINT("MoreauJeanGOSI::computeResidu(), dsType == Type::LagrangianDS\n");
544       // residu = M(q*)(v_k,i+1 - v_i) - h*theta*forces(t_i+1,v_k,i+1, q_k,i+1) - h*(1-theta)*forces(ti,vi,qi) - p_i+1
545       SiconosVector& residu = *ds_work_vectors[MoreauJeanGOSI::RESIDU_FREE];
546       SiconosVector& free_rhs = *ds_work_vectors[MoreauJeanGOSI::FREE];
547 
548       // -- Convert the DS into a Lagrangian one.
549       SP::LagrangianDS d = std::static_pointer_cast<LagrangianDS> (ds);
550 
551       // Get state i (previous time step) from Memories -> var. indexed with "Old"
552       // const SiconosVector& qold = d->qMemory().getSiconosVector(0);
553       const SiconosVector& vold = d->velocityMemory().getSiconosVector(0);
554       SP::SiconosVector q = d->q();
555 
556       SP::SiconosVector v = d->velocity(); // v = v_k,i+1
557       //residu.zero();
558       DEBUG_EXPR(residu.display());
559 
560       // DEBUG_EXPR(qold.display());
561       DEBUG_EXPR(vold.display());
562       DEBUG_EXPR(q->display());
563       DEBUG_EXPR(v->display());
564       free_rhs.zero();
565       SiconosMatrix& W = *_dynamicalSystemsGraph->properties(*dsi).W;
566       prod(W, vold, free_rhs);
567 
568 
569 
570       if(d->forces())
571       {
572         // Cheaper version: get forces(ti,vi,qi) from memory
573         const SiconosVector& fold = d->forcesMemory().getSiconosVector(0);
574         double coef = h * (1 - _theta);
575         scal(coef, fold, free_rhs, false);
576 
577         // Expensive computes forces(ti,vi,qi)
578         // d->computeForces(told, qold, vold);
579         // double coef = -h * (1 - _theta);
580         // // residu += coef * fL_i
581         // scal(coef, *d->forces(), *residu, false);
582 
583         // computes forces(ti+1, v_k,i+1, q_k,i+1) = forces(t,v,q)
584         d->computeForces(t,q,v);
585         coef = h * _theta;
586         scal(coef, *d->forces(), free_rhs, false);
587 
588         // or  forces(ti+1, v_k,i+\theta, q(v_k,i+\theta))
589         //SP::SiconosVector qbasedonv(new SiconosVector(*qold));
590         //*qbasedonv +=  h * ((1 - _theta)* *vold + _theta * *v);
591         //d->computeForces(t, qbasedonv, v);
592         //coef = -h * _theta;
593         // residu += coef * fL_k,i+1
594         //scal(coef, *d->forces(), residu, false);
595 
596 
597       }
598 
599 
600       residu =  -1.0* free_rhs;
601       prod(1.0, W, *v, residu, false);
602 
603       DEBUG_EXPR(residu.display());
604 
605       if(d->p(1))
606         residu -= *d->p(1); // Compute Residu in Workfree Notation !!
607 
608       if(d->boundaryConditions())
609       {
610         THROW_EXCEPTION("MoreauJeanGOSI::computeResidu - boundary conditions not yet implemented for Dynamical system of type: " + Type::name(*ds));
611       }
612 
613 
614       DEBUG_EXPR(residu.display());
615       normResidu = residu.norm2();
616       DEBUG_PRINTF("normResidu= %e\n", normResidu);
617     }
618     // 4 - Lagrangian Linear Systems
619     else if(dsType == Type::LagrangianLinearTIDS)
620     {
621       DEBUG_PRINT("MoreauJeanGOSI::computeResidu(), dsType == Type::LagrangianLinearTIDS\n");
622       // ResiduFree = h*C*v_i + h*Kq_i +h*h*theta*Kv_i+hFext_theta     (1)
623       // This formulae is only valid for the first computation of the residual for v = v_i
624       // otherwise the complete formulae must be applied, that is
625       // ResiduFree = M(v - vold) + h*((1-theta)*(C v_i + K q_i) +theta * ( C*v + K(q_i+h(1-theta)v_i+h theta v)))
626       //                     +hFext_theta     (2)
627       // for v != vi, the formulae (1) is wrong.
628       // in the sequel, only the equation (1) is implemented
629 
630       // -- Convert the DS into a Lagrangian one.
631       SP::LagrangianLinearTIDS d = std::static_pointer_cast<LagrangianLinearTIDS> (ds);
632 
633       // Get state i (previous time step) from Memories -> var. indexed with "Old"
634       const SiconosVector& qold = d->qMemory().getSiconosVector(0); // qi
635       const SiconosVector& vold = d->velocityMemory().getSiconosVector(0); //vi
636 
637       DEBUG_EXPR(qold.display(););
638       DEBUG_EXPR(vold.display(););
639       DEBUG_EXPR(d->q()->display(););
640       DEBUG_EXPR(d->velocity()->display(););
641 
642       SiconosVector& residu = *ds_work_vectors[MoreauJeanGOSI::RESIDU_FREE];
643       SiconosVector& free_rhs = *ds_work_vectors[MoreauJeanGOSI::FREE];
644       // --- ResiduFree computation Equation (1) ---
645       residu.zero();
646       SiconosMatrix& W = *_dynamicalSystemsGraph->properties(*dsi).W;
647       prod(W, vold, free_rhs);
648 
649       double coeff;
650       // -- No need to update W --
651 
652       SP::SiconosVector v = d->velocity(); // v = v_k,i+1
653 
654       SP::SiconosMatrix C = d->C();
655       if(C)
656         prod(h, *C, vold, free_rhs, false); // vfree += h*C*vi
657 
658       SP::SiconosMatrix K = d->K();
659       if(K)
660       {
661         coeff = -h * h * _theta;
662         prod(coeff, *K, vold, residu, false); // vfree += -h^2*_theta*K*vi
663         prod(-h, *K, qold, free_rhs, false); // vfree += -h*K*qi
664       }
665 
666       SP::SiconosVector Fext = d->fExt();
667       if(Fext)
668       {
669         // computes Fext(ti)
670         d->computeFExt(told);
671         coeff = h * (1 - _theta);
672         scal(coeff, *(d->fExt()), free_rhs, false); // vfree += h*(1-_theta) * fext(ti)
673         // computes Fext(ti+1)
674         d->computeFExt(t);
675         coeff = h * _theta;
676         scal(coeff, *(d->fExt()), free_rhs, false); // vfree += h*_theta * fext(ti+1)
677       }
678 
679 
680       if(d->boundaryConditions())
681       {
682         THROW_EXCEPTION("MoreauJeanGOSI::computeResidu - boundary conditions not yet implemented for Dynamical system of type: " + Type::name(*ds));
683       }
684 
685       // residu = -1.0*free_rhs;
686       // prod(1.0, W, *v, residu, false);
687       // DEBUG_EXPR(free_rhs.display());
688       // if(d->p(1))
689       //   residu -= *d->p(1); // Compute Residu in Workfree Notation !!
690 
691       normResidu = 0.0; // we assume that v = vfree + W^(-1) p
692     }
693 
694 
695 
696     else if(dsType == Type::NewtonEulerDS)
697     {
698       DEBUG_PRINT("MoreauJeanGOSI::computeResidu(), dsType == Type::NewtonEulerDS\n");
699       // residu = M (v_k,i+1 - v_i) - h*_theta*forces(t,v_k,i+1, q_k,i+1) - h*(1-_theta)*forces(ti,vi,qi) - pi+1
700 
701 
702       // -- Convert the DS into a Lagrangian one.
703       SP::NewtonEulerDS d = std::static_pointer_cast<NewtonEulerDS> (ds);
704       DEBUG_EXPR(d->display());
705       SiconosVector& residu = *ds_work_vectors[MoreauJeanGOSI::RESIDU_FREE];
706       SiconosVector& free_rhs = *ds_work_vectors[MoreauJeanGOSI::FREE];
707       // Get the state  (previous time step) from memory vector
708       // -> var. indexed with "Old"
709       const SiconosVector& vold = d->twistMemory().getSiconosVector(0);
710 
711 
712       // Get the current state vector
713       SP::SiconosVector q = d->q();
714       SP::SiconosVector v = d->twist(); // v = v_k,i+1
715 
716       DEBUG_EXPR(vold.display());
717       DEBUG_EXPR(q->display());
718       DEBUG_EXPR(v->display());
719 
720 
721       residu.zero();
722       // Get the (constant mass matrix)
723       // SP::SiconosMatrix massMatrix = d->mass();
724       // prod(*massMatrix, (*v - vold), residu, true); // residu = M(v - vold)
725       // DEBUG_EXPR(residu.display(););
726       free_rhs.zero();
727       SiconosMatrix& W = *_dynamicalSystemsGraph->properties(*dsi).W;
728       prod(W, vold, free_rhs);
729 
730 
731 
732       if(d->forces())   // if fL exists
733       {
734         DEBUG_PRINTF("MoreauJeanGOSI:: _theta = %e\n",_theta);
735         DEBUG_PRINTF("MoreauJeanGOSI:: h = %e\n",h);
736 
737         // Cheaper version: get forces(ti,vi,qi) from memory
738         const SiconosVector& fold = d->forcesMemory().getSiconosVector(0);
739         double coef = h * (1 - _theta);
740         scal(coef, fold, free_rhs, false);
741 
742         // Expensive version to check ...
743         //d->computeForces(told,qold,vold);
744         //double coef = -h * (1.0 - _theta);
745         //scal(coef, *d->forces(), residu, false);
746 
747         DEBUG_PRINT("MoreauJeanGOSI:: old forces :\n");
748         DEBUG_EXPR(d->forces()->display(););
749         DEBUG_EXPR(residu.display(););
750 
751         // computes forces(ti,v,q)
752         d->computeForces(t,q,v);
753         coef = h * _theta;
754         scal(coef, *d->forces(), free_rhs, false);
755         DEBUG_PRINT("MoreauJeanGOSI:: new forces :\n");
756         DEBUG_EXPR(d->forces()->display(););
757         DEBUG_EXPR(residu.display(););
758 
759       }
760 
761 
762       if(d->boundaryConditions())
763       {
764         THROW_EXCEPTION("MoreauJeanGOSI::computeResidu - boundary conditions not yet implemented for Dynamical system of type: " + Type::name(*ds));
765       }
766 
767       residu =  -1.0* free_rhs;
768 
769       prod(1.0, W, *v, residu, false);
770 
771 
772       if(d->p(1))
773         residu -= *d->p(1);
774 
775 
776       if(d->boundaryConditions())
777       {
778         THROW_EXCEPTION("MoreauJeanGOSI::computeResidu - boundary conditions not yet implemented for Dynamical system of type: " + Type::name(*ds));
779       }
780 
781       DEBUG_PRINT("MoreauJeanGOSI::computeResidu :\n");
782       DEBUG_EXPR(residu.display(););
783       DEBUG_EXPR(if(d->p(1)) d->p(1)->display(););
784       DEBUG_EXPR(free_rhs.display(););
785 
786       normResidu = residu.norm2();
787       DEBUG_PRINTF("normResidu= %e\n", normResidu);
788     }
789     else
790       THROW_EXCEPTION("MoreauJeanGOSI::computeResidu - not yet implemented for Dynamical system of type: " + Type::name(*ds));
791 
792     if(normResidu > maxResidu) maxResidu = normResidu;
793 
794   }
795   return maxResidu;
796 }
797 
computeFreeState()798 void MoreauJeanGOSI::computeFreeState()
799 {
800   DEBUG_BEGIN("\nMoreauJeanGOSI::computeFreeState()\n");
801 
802   DEBUG_END("MoreauJeanGOSI::computeFreeState()\n");
803 }
804 
prepareNewtonIteration(double time)805 void MoreauJeanGOSI::prepareNewtonIteration(double time)
806 {
807   DEBUG_BEGIN(" MoreauJeanOSI::prepareNewtonIteration(double time)\n");
808   DynamicalSystemsGraph::VIterator dsi, dsend;
809   for(std::tie(dsi, dsend) = _dynamicalSystemsGraph->vertices(); dsi != dsend; ++dsi)
810   {
811     if(!checkOSI(dsi)) continue;
812     SP::DynamicalSystem ds = _dynamicalSystemsGraph->bundle(*dsi);
813     SiconosMatrix& W = *_dynamicalSystemsGraph->properties(*dsi).W;
814     computeW(time, ds, W);
815   }
816 
817   if(!_explicitNewtonEulerDSOperators)
818   {
819     DynamicalSystemsGraph::VIterator dsi, dsend;
820 
821     for(std::tie(dsi, dsend) = _dynamicalSystemsGraph->vertices(); dsi != dsend; ++dsi)
822     {
823       if(!checkOSI(dsi)) continue;
824 
825       SP::DynamicalSystem ds = _dynamicalSystemsGraph->bundle(*dsi);
826 
827       //  VA <2016-04-19 Tue> We compute T to be consistent with the Jacobian at the beginning of the Newton iteration and not at the end
828       Type::Siconos dsType = Type::value(*ds);
829       if(dsType == Type::NewtonEulerDS)
830       {
831         SP::NewtonEulerDS d = std::static_pointer_cast<NewtonEulerDS> (ds);
832         computeT(d->q(),d->T());
833       }
834     }
835   }
836   if(!_explicitJacobiansOfRelation)
837   {
838     _simulation->nonSmoothDynamicalSystem()->computeInteractionJacobians(time);
839   }
840 
841 
842   DEBUG_END(" MoreauJeanOSI::prepareNewtonIteration(double time)\n");
843 
844 }
845 
846 
847 struct MoreauJeanGOSI::_NSLEffectOnFreeOutput : public SiconosVisitor
848 {
849   using SiconosVisitor::visit;
850 
851   OneStepNSProblem& _osnsp;
852   Interaction& _inter;
853   InteractionProperties& _interProp;
854 
_NSLEffectOnFreeOutputMoreauJeanGOSI::_NSLEffectOnFreeOutput855   _NSLEffectOnFreeOutput(OneStepNSProblem& p, Interaction& inter, InteractionProperties& interProp) :
856     _osnsp(p), _inter(inter), _interProp(interProp) {};
857 
visitMoreauJeanGOSI::_NSLEffectOnFreeOutput858   void visit(const NewtonImpactNSL& nslaw)
859   {
860     double e;
861     e = nslaw.e();
862     Index subCoord(4);
863     subCoord[0] = 0;
864     subCoord[1] = _inter.nonSmoothLaw()->size();
865     subCoord[2] = 0;
866     subCoord[3] = subCoord[1];
867     SiconosVector & osnsp_rhs = *(*_interProp.workVectors)[MoreauJeanGOSI::OSNSP_RHS];
868     subscal(e, *_inter.y_k(_osnsp.inputOutputLevel()), osnsp_rhs, subCoord, true);
869   }
870 
visitMoreauJeanGOSI::_NSLEffectOnFreeOutput871   void visit(const NewtonImpactFrictionNSL& nslaw)
872   {
873     SiconosVector & osnsp_rhs = *(*_interProp.workVectors)[MoreauJeanGOSI::OSNSP_RHS];
874     DEBUG_PRINTF("y_k = %e\n", (*_inter.y_k(_osnsp.inputOutputLevel()))(0));
875     DEBUG_PRINTF("level = %i\n", _osnsp.inputOutputLevel());
876     if(nslaw.en() > 0.0)
877     {
878       osnsp_rhs(0) =  nslaw.en()  * (*_inter.y_k(_osnsp.inputOutputLevel()))(0);
879     }
880     // The tangential part is multiplied depends on et
881     if(nslaw.et() > 0.0)
882     {
883       osnsp_rhs(1) =  nslaw.et()  * (*_inter.y_k(_osnsp.inputOutputLevel()))(1);
884       if(_inter.nonSmoothLaw()->size()>=2)
885       {
886         osnsp_rhs(2) =  nslaw.et()  * (*_inter.y_k(_osnsp.inputOutputLevel()))(2);
887       }
888     }
889   }
visitMoreauJeanGOSI::_NSLEffectOnFreeOutput890   void visit(const NewtonImpactRollingFrictionNSL& nslaw)
891   {
892     SiconosVector & osnsp_rhs = *(*_interProp.workVectors)[MoreauJeanGOSI::OSNSP_RHS];
893     DEBUG_PRINTF("y_k = %e\n", (*_inter.y_k(_osnsp.inputOutputLevel()))(0));
894     DEBUG_PRINTF("level = %i\n", _osnsp.inputOutputLevel());
895 
896     if(nslaw.en() > 0.0)
897     {
898       osnsp_rhs(0) =  nslaw.en()  * (*_inter.y_k(_osnsp.inputOutputLevel()))(0);
899     }
900     // The tangential part is multiplied depends on et
901     if(nslaw.et() > 0.0)
902     {
903       osnsp_rhs(1) =  nslaw.et()  * (*_inter.y_k(_osnsp.inputOutputLevel()))(1);
904       if(_inter.nonSmoothLaw()->size()>=2)
905       {
906         osnsp_rhs(2) =  nslaw.et()  * (*_inter.y_k(_osnsp.inputOutputLevel()))(2);
907       }
908     }
909   }
visitMoreauJeanGOSI::_NSLEffectOnFreeOutput910   void visit(const EqualityConditionNSL& nslaw)
911   {
912     ;
913   }
visitMoreauJeanGOSI::_NSLEffectOnFreeOutput914   void visit(const MixedComplementarityConditionNSL& nslaw)
915   {
916     ;
917   }
918 };
919 
NSLcontrib(SP::Interaction inter,OneStepNSProblem & osnsp)920 void MoreauJeanGOSI::NSLcontrib(SP::Interaction inter, OneStepNSProblem& osnsp)
921 {
922   if(inter->relation()->getType() == Lagrangian || inter->relation()->getType() == NewtonEuler)
923   {
924     InteractionsGraph& indexSet = *osnsp.simulation()->indexSet(osnsp.indexSetLevel());
925     InteractionsGraph::VDescriptor ivd = indexSet.descriptor(inter);
926     _NSLEffectOnFreeOutput nslEffectOnFreeOutput = _NSLEffectOnFreeOutput(osnsp, *inter, indexSet.properties(ivd));
927     inter->nonSmoothLaw()->accept(nslEffectOnFreeOutput);
928   }
929 }
930 
integrate(double & tinit,double & tend,double & tout,int & notUsed)931 void MoreauJeanGOSI::integrate(double& tinit, double& tend, double& tout, int& notUsed)
932 {
933 }
934 
updatePosition(DynamicalSystem & ds)935 void MoreauJeanGOSI::updatePosition(DynamicalSystem& ds)
936 {
937   DEBUG_END("MoreauJeanGOSI::updatePosition(const unsigned int )\n");
938   double h = _simulation->timeStep();
939 
940   Type::Siconos dsType = Type::value(ds);
941 
942   // 1 - Lagrangian Systems
943   if(dsType == Type::LagrangianDS || dsType == Type::LagrangianLinearTIDS)
944   {
945     // get dynamical system
946 
947     LagrangianDS& d = static_cast<LagrangianDS&>(ds);
948 
949     // Compute q
950     SiconosVector& v = *d.velocity();
951     SiconosVector& q = *d.q();
952     DEBUG_EXPR(v.display());
953     DEBUG_EXPR(q.display());
954 
955     //  -> get previous time step state
956     const SiconosVector& vold = d.velocityMemory().getSiconosVector(0);
957     const SiconosVector& qold = d.qMemory().getSiconosVector(0);
958     // *q = *qold + h*(theta * *v +(1.0 - theta)* *vold)
959     double coeff = h * _theta;
960     scal(coeff, v, q) ; // q = h*theta*v
961     coeff = h * (1 - _theta);
962     scal(coeff, vold, q, false); // q += h(1-theta)*vold
963     q += qold;
964     DEBUG_EXPR(v.display());
965     DEBUG_EXPR(q.display());
966 
967   }
968   else if(dsType == Type::NewtonEulerDS)
969   {
970     // get dynamical system
971     NewtonEulerDS& d = static_cast<NewtonEulerDS&>(ds);
972     const SiconosVector& v = *d.twist();
973     DEBUG_PRINT("MoreauJeanGOSI::updateState()\n ")
974     DEBUG_EXPR(d.display());
975 
976     //compute q
977     //first step consists in computing  \dot q.
978     //second step consists in updating q.
979     //
980     SP::SiconosMatrix T = d.T();
981     SiconosVector& dotq = *d.dotq();
982     prod(*T, v, dotq, true);
983 
984     DEBUG_PRINT("MoreauJeanGOSI::updateState v\n");
985     DEBUG_EXPR(v.display());
986     DEBUG_EXPR(dotq.display());
987 
988     SiconosVector& q = *d.q();
989 
990     //  -> get previous time step state
991     const SiconosVector& dotqold = d.dotqMemory().getSiconosVector(0);
992     const SiconosVector& qold = d.qMemory().getSiconosVector(0);
993     // *q = *qold + h*(theta * *v +(1.0 - theta)* *vold)
994     double coeff = h * _theta;
995     scal(coeff, dotq, q) ; // q = h*theta*v
996     coeff = h * (1 - _theta);
997     scal(coeff, dotqold, q, false); // q += h(1-theta)*vold
998     q += qold;
999     DEBUG_PRINT("new q before normalizing\n");
1000     DEBUG_EXPR(q.display());
1001 
1002     //q[3:6] must be normalized
1003     d.normalizeq();
1004 
1005     /* \warning VA 02/06/2013.
1006      * What is the reason of doing the following computation ?
1007      */
1008     // dotq->setValue(3, (q->getValue(3) - qold->getValue(3)) / h);
1009     // dotq->setValue(4, (q->getValue(4) - qold->getValue(4)) / h);
1010     // dotq->setValue(5, (q->getValue(5) - qold->getValue(5)) / h);
1011     // dotq->setValue(6, (q->getValue(6) - qold->getValue(6)) / h);
1012 
1013     // d->computeT(); //  VA 09/06/2015. We prefer only compute T() every time--step for Newton convergence reasons.
1014 
1015   }
1016   DEBUG_END("MoreauJeanGOSI::updatePosition(const unsigned int )\n");
1017 
1018 }
1019 
updateState(const unsigned int)1020 void MoreauJeanGOSI::updateState(const unsigned int)
1021 {
1022 
1023   DEBUG_PRINT("MoreauJeanGOSI::updateState(const unsigned int )\n");
1024 
1025   double RelativeTol = _simulation->relativeConvergenceTol();
1026   bool useRCC = _simulation->useRelativeConvergenceCriteron();
1027   if(useRCC)
1028     _simulation->setRelativeConvergenceCriterionHeld(true);
1029 
1030   DynamicalSystemsGraph::VIterator dsi, dsend;
1031   for(std::tie(dsi, dsend) = _dynamicalSystemsGraph->vertices(); dsi != dsend; ++dsi)
1032   {
1033     if(!checkOSI(dsi)) continue;
1034     DynamicalSystem& ds = *_dynamicalSystemsGraph->bundle(*dsi);
1035     VectorOfVectors& ds_work_vectors = *_dynamicalSystemsGraph->properties(*dsi).workVectors;
1036 
1037     // Get the DS type
1038 
1039     Type::Siconos dsType = Type::value(ds);
1040 
1041     // 3 - Lagrangian Systems
1042     if(dsType == Type::LagrangianDS || dsType == Type::LagrangianLinearTIDS)
1043     {
1044       LagrangianDS& d = static_cast<LagrangianDS&>(ds);
1045       bool baux = dsType == Type::LagrangianDS && useRCC && _simulation->relativeConvergenceCriterionHeld();
1046 
1047       SiconosVector &q = *d.q();
1048       SiconosVector& local_buffer = *ds_work_vectors[MoreauJeanGOSI::LOCAL_BUFFER];
1049 
1050       // Save value of q in stateTmp for future convergence computation
1051       if(baux)
1052         local_buffer = q;
1053 
1054       updatePosition(ds);
1055 
1056       if(baux)
1057       {
1058         double ds_norm_ref = 1. + ds.x0()->norm2(); // Should we save this in the graph?
1059         local_buffer -= q;
1060         double aux = (local_buffer.norm2()) / ds_norm_ref;
1061         if(aux > RelativeTol)
1062           _simulation->setRelativeConvergenceCriterionHeld(false);
1063       }
1064     }
1065     else if(dsType == Type::NewtonEulerDS)
1066     {
1067       DEBUG_PRINT("MoreauJeanGOSI::updateState(const unsigned int ), dsType == Type::NewtonEulerDS \n");
1068       updatePosition(ds);
1069     }
1070     else THROW_EXCEPTION("MoreauJeanGOSI::updateState - not yet implemented for Dynamical system of type: " +  Type::name(ds));
1071 
1072   }
1073 }
1074 
1075 
addInteractionInIndexSet(SP::Interaction inter,unsigned int i)1076 bool MoreauJeanGOSI::addInteractionInIndexSet(SP::Interaction inter, unsigned int i)
1077 {
1078   DEBUG_PRINT("addInteractionInIndexSet(SP::Interaction inter, unsigned int i)\n");
1079 
1080   assert(i == 1);
1081   double h = _simulation->timeStep();
1082   double y = (inter->y(i - 1))->getValue(0); // for i=1 y(i-1) is the position
1083   double yDot = (inter->y(i))->getValue(0); // for i=1 y(i) is the velocity
1084 
1085   double gamma = 1.0 / 2.0;
1086   if(_useGamma)
1087   {
1088     gamma = _gamma;
1089   }
1090   DEBUG_PRINTF("MoreauJeanGOSI::addInteractionInIndexSet of level = %i y=%e, yDot=%e, y_estimated=%e.\n", i,  y, yDot, y + gamma * h * yDot);
1091   y += gamma * h * yDot;
1092 
1093   DEBUG_PRINTF("y = %e\n", y);
1094   assert(!std::isnan(y));
1095   DEBUG_EXPR_WE(
1096     if(y <= 0)
1097 {
1098   DEBUG_PRINT("MoreauJeanGOSI::addInteractionInIndexSet ACTIVATED.\n");
1099   }
1100   else
1101   {
1102     DEBUG_PRINT("MoreauJeanGOSI::addInteractionInIndexSet NOT ACTIVATED.\n");
1103   }
1104   );
1105   return (y <= 0.0);
1106 }
1107 
1108 
removeInteractionFromIndexSet(SP::Interaction inter,unsigned int i)1109 bool MoreauJeanGOSI::removeInteractionFromIndexSet(SP::Interaction inter, unsigned int i)
1110 {
1111   assert(i == 1);
1112   double h = _simulation->timeStep();
1113   double y = (inter->y(i - 1))->getValue(0); // for i=1 y(i-1) is the position
1114   double yDot = (inter->y(i))->getValue(0); // for i=1 y(i) is the velocity
1115   double gamma = 1.0 / 2.0;
1116   if(_useGamma)
1117   {
1118     gamma = _gamma;
1119   }
1120   DEBUG_PRINTF("MoreauJeanGOSI::addInteractionInIndexSet yref=%e, yDot=%e, y_estimated=%e.\n", y, yDot, y + gamma * h * yDot);
1121   y += gamma * h * yDot;
1122   assert(!std::isnan(y));
1123 
1124   DEBUG_EXPR(
1125     if(y > 0)
1126     DEBUG_PRINT("MoreauJeanGOSI::removeInteractionFromIndexSet DEACTIVATE.\n");
1127   );
1128   return (y > 0.0);
1129 }
1130 
1131 
1132 
display()1133 void MoreauJeanGOSI::display()
1134 {
1135   OneStepIntegrator::display();
1136 
1137   std::cout << "====== MoreauJeanOSI OSI display ======" <<std::endl;
1138   DynamicalSystemsGraph::VIterator dsi, dsend;
1139   if(_dynamicalSystemsGraph)
1140   {
1141     for(std::tie(dsi, dsend) = _dynamicalSystemsGraph->vertices(); dsi != dsend; ++dsi)
1142     {
1143       if(!checkOSI(dsi)) continue;
1144       SP::DynamicalSystem ds = _dynamicalSystemsGraph->bundle(*dsi);
1145 
1146       std::cout << "--------------------------------" <<std::endl;
1147       std::cout << "--> W of dynamical system number " << ds->number() << ": " <<std::endl;
1148       if(_dynamicalSystemsGraph->properties(*dsi).W) _dynamicalSystemsGraph->properties(*dsi).W->display();
1149       else std::cout << "-> nullptr" <<std::endl;
1150       std::cout << "--> and corresponding theta is: " << _theta <<std::endl;
1151     }
1152   }
1153   std::cout << "================================" <<std::endl;
1154 }
1155