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 
19 #include "TimeStepping.hpp"
20 
21 #include "TimeSteppingDirectProjection.hpp"
22 #include "LagrangianDS.hpp"
23 #include "NewtonEulerDS.hpp"
24 #include "NewtonEuler1DR.hpp"
25 #include "OneStepIntegrator.hpp"
26 #include "NonSmoothLaw.hpp"
27 #include "NewtonEulerR.hpp"
28 #include "NonSmoothDynamicalSystem.hpp"
29 #include "OneStepNSProblem.hpp"
30 #include "MoreauJeanOSI.hpp"
31 
32 static CheckSolverFPtr checkSolverOutputProjectOnConstraints = nullptr;
33 // #define DEBUG_NOCOLOR
34 // #define DEBUG_STDOUT
35 // #define DEBUG_MESSAGES
36 #include "siconos_debug.h"
37 //#define CORRECTIONSVELOCITIES
TimeSteppingDirectProjection(SP::NonSmoothDynamicalSystem nsds,SP::TimeDiscretisation td,SP::OneStepIntegrator osi,SP::OneStepNSProblem osnspb_velo,SP::OneStepNSProblem osnspb_pos,unsigned int level)38 TimeSteppingDirectProjection::TimeSteppingDirectProjection(
39   SP::NonSmoothDynamicalSystem nsds,
40   SP::TimeDiscretisation td,
41   SP::OneStepIntegrator osi,
42   SP::OneStepNSProblem osnspb_velo,
43   SP::OneStepNSProblem osnspb_pos,
44   unsigned int level)
45   : TimeStepping(nsds,td, osi, osnspb_velo)
46 {
47 
48   //if (Type::value(osi) != Type::MoreauJeanDirectProjectionOSI)
49   OSI::TYPES typeOSI;
50   typeOSI = (osi)->getType();
51   if(typeOSI != OSI::MOREAUDIRECTPROJECTIONOSI)
52     THROW_EXCEPTION("TimeSteppingDirectProjection::TimeSteppingDirectProjection.  wrong type of OneStepIntegrator");
53 
54   (*_allNSProblems).resize(SICONOS_NB_OSNSP_TSP);
55   insertNonSmoothProblem(osnspb_pos, SICONOS_OSNSP_TS_POS);
56 
57   _indexSetLevelForProjection = level;
58   _constraintTol = 1e-04;
59   _constraintTolUnilateral = 1e-08;
60   _projectionMaxIteration = 10;
61   _doProj = 1;
62   _doOnlyProj = 0;
63   _maxViolationUnilateral = 0.0;
64   _maxViolationEquality = 0.0;
65 
66 }
67 
68 // --- Destructor ---
~TimeSteppingDirectProjection()69 TimeSteppingDirectProjection::~TimeSteppingDirectProjection()
70 {
71 }
72 
initOSNS()73 void TimeSteppingDirectProjection::initOSNS()
74 {
75   TimeStepping::initOSNS();
76 
77   (*_allNSProblems)[SICONOS_OSNSP_TS_POS]->setIndexSetLevel(_indexSetLevelForProjection);
78   (*_allNSProblems)[SICONOS_OSNSP_TS_POS]->setInputOutputLevel(0);
79 
80   (*_allNSProblems)[SICONOS_OSNSP_TS_VELOCITY]->setIndexSetLevel(1);
81   (*_allNSProblems)[SICONOS_OSNSP_TS_VELOCITY]->setInputOutputLevel(1);
82 }
83 
nextStep()84 void TimeSteppingDirectProjection::nextStep()
85 {
86   TimeStepping::nextStep();
87 
88 
89   // Zeroing Lambda Muliplier of indexSet()
90 
91   SP::InteractionsGraph indexSet = _nsds->topology()->indexSet(0);
92   InteractionsGraph::VIterator ui, uiend;
93   for(std::tie(ui, uiend) = indexSet->vertices(); ui != uiend; ++ui)
94   {
95     SP::Interaction inter = indexSet->bundle(*ui);
96     inter->lambda(0)->zero();
97   }
98 
99 }
100 
advanceToEvent()101 void TimeSteppingDirectProjection::advanceToEvent()
102 {
103 
104   initialize();
105 
106   /** First step, Solve the standard velocity formulation.*/
107 
108   DEBUG_BEGIN("TimeStepping::newtonSolve\n");
109 
110   if(!_doOnlyProj)
111     TimeStepping::newtonSolve(_newtonTolerance, _newtonMaxIteration);
112   else
113     updateInteractions();
114 
115   DEBUG_EXPR_WE(std::cout << "TimeStepping::newtonSolve end : Number of iterations=" << getNewtonNbIterations() << "\n";
116                 std::cout << "                              : newtonResiduDSMax=" << newtonResiduDSMax() << "\n";
117                 std::cout << "                              : newtonResiduYMax=" << newtonResiduYMax() << "\n";
118                 std::cout << "                              : newtonResiduRMax=" << newtonResiduRMax() << "\n";
119                );
120 
121   if(!_doProj)
122     return;
123   int info = 0;
124 
125   /** Second step, Perform the projection on constraints.*/
126 
127   DEBUG_PRINT("TimeSteppingDirectProjection::newtonSolve begin projection:\n");
128 
129   SP::DynamicalSystemsGraph dsGraph = _nsds->dynamicalSystems();
130 
131 
132 #ifdef TSPROJ_CORRECTIONVELOCITIES
133   for(DynamicalSystemsGraph::VIterator vi = dsGraph->begin(); vi != dsGraph->end(); ++vi)
134   {
135     SP::DynamicalSystem ds = dsGraph->bundle(*vi);
136     Type::Siconos dsType = Type::value(*ds);
137     if(dsType != Type::NewtonEulerDS)
138       THROW_EXCEPTION("TS:: - ds is not from NewtonEulerDS.");
139     SP::NewtonEulerDS neds = std::static_pointer_cast<NewtonEulerDS>(ds);
140     *(neds->deltaq()) = *(neds->q());
141   }
142 #endif
143 
144   bool runningProjection = false;
145   _nbProjectionIteration = 0;
146   // for (InteractionsIterator it = allInteractions->begin(); it != allInteractions->end(); it++){
147   //   double criteria = (*it)->relation()->y(0)->getValue(0);
148   //   if (Type::value(*((*it)->nonSmoothLaw())) ==  Type::NewtonImpactFrictionNSL ||
149   //  Type::value(*((*it)->nonSmoothLaw())) == Type::NewtonImpactNSL){
150   //     SP::NewtonEuler1DR ri = std::static_pointer_cast<NewtonEuler1DR> ((*it)->relation());
151   //     if (criteria < -1e-7){
152   //  ri->_isOnContact=true;
153   //     }else{
154   //  ri->_isOnContact=false;
155   //     }
156   //   }
157   //   if (criteria < -_constraintTol)
158   //     runningNewton=true;
159   // }
160   if(_nsds->topology()->numberOfIndexSet() > _indexSetLevelForProjection)
161     computeCriteria(&runningProjection);
162   // Zeroing Lambda Muliplier of indexSet()
163 
164   SP::InteractionsGraph indexSet = _nsds->topology()->indexSet(0);
165   InteractionsGraph::VIterator ui, uiend;
166   for(std::tie(ui, uiend) = indexSet->vertices(); ui != uiend; ++ui)
167   {
168     SP::Interaction inter = indexSet->bundle(*ui);
169     inter->lambda(0)->zero();
170   }
171   _nsds->updateInput(nextTime(),0);
172 
173   //Store the q vector of each DS.
174 
175   for(DynamicalSystemsGraph::VIterator aVi2 = dsGraph->begin(); aVi2 != dsGraph->end(); ++aVi2)
176   {
177     SP::DynamicalSystem ds = dsGraph->bundle(*aVi2);
178     Type::Siconos dsType = Type::value(*ds);
179     VectorOfVectors& workVectors = *dsGraph->properties(*aVi2).workVectors;
180     if(dsType == Type::NewtonEulerDS)
181     {
182       SP::NewtonEulerDS neds = std::static_pointer_cast<NewtonEulerDS>(ds);
183       *workVectors[MoreauJeanOSI::QTMP] = *neds->q();
184     }
185     else if(dsType == Type::LagrangianDS || dsType == Type::LagrangianLinearTIDS)
186     {
187       SP::LagrangianDS d = std::static_pointer_cast<LagrangianDS> (ds);
188       *workVectors[MoreauJeanOSI::QTMP] = * d->q();
189 
190     }
191     else
192       THROW_EXCEPTION("TimeSteppingDirectProjection::advanceToEvent() :: - Ds is not from NewtonEulerDS neither from LagrangianDS.");
193   }
194 
195   while(runningProjection && _nbProjectionIteration < _projectionMaxIteration)
196   {
197     _nbProjectionIteration++;
198     DEBUG_PRINTF("TimeSteppingDirectProjection projection step = %d\n", _nbProjectionIteration);
199 
200     SP::InteractionsGraph indexSet = _nsds->topology()->indexSet(0);
201     InteractionsGraph::VIterator ui, uiend;
202     for(std::tie(ui, uiend) = indexSet->vertices(); ui != uiend; ++ui)
203     {
204       SP::Interaction inter = indexSet->bundle(*ui);
205       inter->lambda(0)->zero();
206     }
207     _nsds->updateInput(nextTime(),0);
208     info = 0;
209 
210     DEBUG_PRINT("TimeSteppingProjectOnConstraint compute OSNSP.\n");
211 
212     info = computeOneStepNSProblem(SICONOS_OSNSP_TS_POS);
213 
214     DEBUG_PRINTF("IndexSet0->size() = %i\n", (int)_nsds->topology()->indexSet(0)->size());
215     DEBUG_PRINTF("IndexSet1->size() = %i\n", (int)_nsds->topology()->indexSet(1)->size());
216     DEBUG_EXPR(oneStepNSProblem(SICONOS_OSNSP_TS_POS)->display());
217 
218 
219     if(info && _warnOnNonConvergence)
220     {
221       std::cout << "[kernel] TimeSteppingDirectProjection::advanceToEvent() project on constraints. solver failed." <<std::endl ;
222     }
223     _nsds->updateInput(nextTime(),0);
224 
225     DEBUG_EXPR_WE(std ::cout << "After update input" << std::endl;
226                   SP::InteractionsGraph indexSet1 = _nsds->topology()->indexSet(1);
227                   std ::cout << "lamda(1) in IndexSet1" << std::endl;
228                   for(std::tie(ui, uiend) = indexSet1->vertices(); ui != uiend; ++ui)
229   {
230     SP::Interaction inter = indexSet1->bundle(*ui);
231       inter->lambda(1)->display();
232     }
233     SP::InteractionsGraph indexSet0 = _nsds->topology()->indexSet(0);
234                                       std ::cout << "lamda(0) in indexSet0" << std::endl;
235                                       for(std::tie(ui, uiend) = indexSet0->vertices(); ui != uiend; ++ui)
236   {
237     SP::Interaction inter = indexSet0->bundle(*ui);
238       inter->lambda(0)->display();
239     }
240                  );
241 
242     // This part should be in MoreauJeanOSIProjectOnConstraintsOS::updateState(level =0)
243     for(DynamicalSystemsGraph::VIterator aVi2 = dsGraph->begin(); aVi2 != dsGraph->end(); ++aVi2)
244     {
245       SP::DynamicalSystem ds = dsGraph->bundle(*aVi2);
246       VectorOfVectors& workVectors = *dsGraph->properties(*aVi2).workVectors;
247 
248       Type::Siconos dsType = Type::value(*ds);
249       if(dsType == Type::NewtonEulerDS)
250       {
251         SP::NewtonEulerDS neds = std::static_pointer_cast<NewtonEulerDS>(ds);
252         SP::SiconosVector q = neds->q();
253         SP::SiconosVector qtmp =  workVectors[MoreauJeanOSI::QTMP];
254 
255         DEBUG_EXPR_WE(std ::cout << "qtmp before  update " << std::endl;
256                       qtmp->display();
257                       std ::cout << "p(0) before  update " << std::endl;
258                       neds->p(0)->display();
259                      );
260 
261         if(neds->p(0))
262         {
263           //*q = * qtmp +  *neds->p(0);
264           *q += *neds->p(0); // Why it works like that and not with the previous line ?
265         }
266 
267         DEBUG_EXPR_WE(std ::cout << "q after  update " << std::endl;
268                       q->display(););
269 
270         neds->normalizeq();
271         neds->computeT();
272       }
273       else if(dsType == Type::LagrangianDS || dsType == Type::LagrangianLinearTIDS)
274       {
275         SP::LagrangianDS d = std::static_pointer_cast<LagrangianDS> (ds);
276         SP::SiconosVector q = d->q();
277         SP::SiconosVector qtmp =  workVectors[MoreauJeanOSI::QTMP];
278 
279         if(d->p(0))
280         {
281           //*q = * qtmp +  *d->p(0);
282           *q += *d->p(0);
283         }
284       }
285       else
286         THROW_EXCEPTION("TimeSteppingDirectProjection::advanceToEvent() :: - Ds is not from NewtonEulerDS neither from LagrangianDS.");
287 
288     }
289 
290     computeCriteria(&runningProjection);
291 
292     //cout<<"||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||  Z:"<<endl;
293     //(*_allNSProblems)[SICONOS_OSNSP_TS_POS]->display();
294     //(std::static_pointer_cast<LinearOSNS>((*_allNSProblems)[SICONOS_OSNSP_TS_POS]))->z()->display();
295 
296     DEBUG_EXPR_WE(std::cout << "TimeSteppingDirectProjection::Projection end : Number of iterations=" << _nbProjectionIteration << "\n";
297                   std ::cout << "After update state in position" << std::endl;
298                   std ::cout << "lamda(1) in IndexSet1" << std::endl;
299                   SP::InteractionsGraph indexSet1 = _nsds->topology()->indexSet(1);
300                   SP::InteractionsGraph indexSet0 = _nsds->topology()->indexSet(0);
301 
302                   for(std::tie(ui, uiend) = indexSet1->vertices(); ui != uiend; ++ui)
303   {
304     SP::Interaction inter = indexSet1->bundle(*ui);
305       inter->lambda(1)->display();
306     }
307     std ::cout << "lamda(0) in indexSet0" << std::endl;
308                for(std::tie(ui, uiend) = indexSet0->vertices(); ui != uiend; ++ui)
309   {
310     SP::Interaction inter = indexSet0->bundle(*ui);
311       inter->lambda(0)->display();
312     }
313     std ::cout << "y(1) in IndexSet1" << std::endl;	       for(std::tie(ui, uiend) = indexSet1->vertices(); ui != uiend; ++ui)
314   {
315     SP::Interaction inter = indexSet1->bundle(*ui);
316       inter->y(1)->display();
317     }
318     std ::cout << "y(0) in indexSet0" << std::endl;
319                for(std::tie(ui, uiend) = indexSet0->vertices(); ui != uiend; ++ui)
320   {
321     SP::Interaction inter = indexSet0->bundle(*ui);
322       inter->y(0)->display();
323     }
324                  );
325 
326 
327     //cout<<"during projection before normalizing of q:\n";
328     //for (InteractionsIterator it = allInteractions->begin(); it != allInteractions->end(); it++)
329     //{
330     //  (*it)->relation()->computeh(getTkp1());
331     //}
332   }// end while(runningProjection && _nbProjectionIteration < _projectionMaxIteration)
333 
334   // We update forces to start the Newton Loop the next tiem step with a correct value in swap
335   for(DynamicalSystemsGraph::VIterator aVi2 = dsGraph->begin(); aVi2 != dsGraph->end(); ++aVi2)
336   {
337     SP::DynamicalSystem ds = dsGraph->bundle(*aVi2);
338     Type::Siconos dsType = Type::value(*ds);
339     if(dsType == Type::NewtonEulerDS)
340     {
341       SP::NewtonEulerDS neds = std::static_pointer_cast<NewtonEulerDS>(ds);
342       double time = nextTime();
343       neds->computeForces(time, neds->q(), neds->twist());
344     }
345     else if(dsType == Type::LagrangianDS)
346     {
347       SP::LagrangianDS d = std::static_pointer_cast<LagrangianDS> (ds);
348       double time = nextTime();
349       d->computeForces(time, d->q(), d->velocity());
350     }
351     else if(dsType == Type::LagrangianLinearTIDS)
352     {
353     }
354     else
355       THROW_EXCEPTION("TimeSteppingCombinedProjection::advanceToEvent() - Ds is not from NewtonEulerDS neither from LagrangianDS.");
356   }
357 
358 
359 
360 
361 
362 
363 
364   if(_nbProjectionIteration == _projectionMaxIteration && _warnOnNonConvergence)
365   {
366     std::cout << "[kernel] TimeSteppingDirectProjection::advanceToEvent() Max number of projection iterations reached (" << _nbProjectionIteration << ")"  <<std::endl ;
367     printf("[kernel]                max criteria equality =  %e.\n", _maxViolationEquality);
368     printf("[kernel]                max criteria unilateral =  %e.\n", _maxViolationUnilateral);
369   }
370 
371 
372   DEBUG_END("TimeSteppingDirectProjection::newtonSolve()\n");
373 
374   return;
375   //#ifdef TSPROJ_CORRECTIONVELOCITIES
376   //   /*The following reduces the velocity because the position step increase the energy of the system. This formulation works only with simple systems.To activate it, comment the next line.*/
377 
378   //   for(DynamicalSystemsGraph::VIterator vi = dsGraph->begin(); vi != dsGraph->end(); ++vi)
379   //   {
380   //     SP::DynamicalSystem ds = dsGraph->bundle(*vi);
381   //     Type::Siconos dsType = Type::value(*ds);
382   //     if(dsType !=Type::NewtonEulerDS)
383   //       THROW_EXCEPTION("TS:: - ds is not from NewtonEulerDS.");
384   //     // SP::SiconosVector dotq = neds->dotq();
385   //     // SP::SiconosVector q = neds->q();
386   //     // SP::SiconosVector qold = neds->qMemory()->getSiconosVector(0);
387   //     // double h = timeStep();
388   //     // dotq->setValue(3,(q->getValue(3)-qold->getValue(3))/h);
389   //     // dotq->setValue(4,(q->getValue(4)-qold->getValue(4))/h);
390   //     // dotq->setValue(5,(q->getValue(5)-qold->getValue(5))/h);
391   //     // dotq->setValue(6,(q->getValue(6)-qold->getValue(6))/h);
392 
393   //     /*compute the new velocity seeing the work of fext*/
394   //     SP::NewtonEulerDS neds = std::static_pointer_cast<NewtonEulerDS>(ds);
395   //     *(neds->deltaq())-=*(neds->q());
396   //     DEBUG_EXPR(printf("TSProj NewtonSolve :deltaq:");
397   //     (neds->deltaq())->display(););
398   //     //continue;
399   //     double  n2q=neds->deltaq()->norm2();
400   //     double n2=0.0;
401   //     if(neds->fExt())
402   //       n2=neds->fExt()->norm2();
403   //     if(n2 > 1e-7 && n2q > 1e-14)
404   //     {
405   //       //if (n2q < 1e-14)
406   //       // continue;
407 
408   //       SP::SiconosVector FextNorm(new SiconosVector(3));
409   //       FextNorm->setValue(0,neds->fExt()->getValue(0));
410   //       FextNorm->setValue(1,neds->fExt()->getValue(1));
411   //       FextNorm->setValue(2,neds->fExt()->getValue(2));
412   // DEBUG_EXPR_WE(
413   //       std::cout<<"TimeSteppingDirectProjection::newtonSolve deltaQ :\n";
414   //       neds->deltaq()->display();
415   //       std::cout<<"TimeSteppingDirectProjection::newtonSolve Fext :\n";
416   //       FextNorm->display();
417   //       );
418 
419   //       (*FextNorm)*=(1./n2);
420   //       /*work of external forces.*/
421   //       double workFext= neds->fExt()->getValue(0) * neds->deltaq()->getValue(0)+
422   //                        neds->fExt()->getValue(1) * neds->deltaq()->getValue(1)+
423   //                        neds->fExt()->getValue(2) * neds->deltaq()->getValue(2);
424   //       //workFext*=2.0;
425   //       double VkFNorm=FextNorm->getValue(0)*neds->velocity()->getValue(0)+
426   //                      FextNorm->getValue(1)*neds->velocity()->getValue(1)+
427   //                      FextNorm->getValue(2)*neds->velocity()->getValue(2);
428   //       double VkcFNorm =VkFNorm;
429   //       VkcFNorm= VkFNorm*VkFNorm - 2*fabs(workFext)/(neds->massValue());
430   //       if(VkcFNorm >0)
431   //       {
432   //         if(VkFNorm>0)
433   //           VkcFNorm=sqrt(VkcFNorm);
434   //         else
435   //           VkcFNorm=-sqrt(VkcFNorm);
436   //       }
437   //       else
438   //         VkcFNorm=0;
439   //       // if (VkFNorm >= 0 && workFext >0){
440   //       //   ;//VkcFNorm=sqrt (2*workFext/(neds->massValue())+VkFNorm*VkFNorm);
441   //       // }else if (VkFNorm <= 0 && workFext < 0){
442   //       //   ;//VkcFNorm=-sqrt (fabs(2*workFext/(neds->massValue())+VkFNorm*VkFNorm));
443   //       // }else if (VkFNorm > 0 && workFext <0){
444   //       //   VkcFNorm= VkFNorm*VkFNorm + 2*workFext/(neds->massValue());
445   //       //   if (VkcFNorm >0)
446   //       //     VkcFNorm=sqrt(VkcFNorm);
447   //       //   else
448   //       //     VkcFNorm=0;
449   //       // }else if (VkFNorm < 0 && workFext > 0){
450   //       //   VkcFNorm= VkFNorm*VkFNorm - 2*workFext/(neds->massValue());
451   //       //   if (VkcFNorm >0)
452   //       //     VkcFNorm=-sqrt(VkcFNorm);
453   //       //   else
454   //       //     VkcFNorm=0;
455   //       // }
456   // DEBUG_EXPR_WE(
457   //       printf("TimeSteppingDirectProjection::newtonSolve velocity before update(prevComp=%e, newComp=%e)\n",VkFNorm,VkcFNorm);
458   //       printf("VELOCITY1 ");
459   //       neds->velocity()->display();
460   // );
461   //       neds->velocity()->setValue(0,neds->velocity()->getValue(0)+(VkcFNorm - VkFNorm)*FextNorm->getValue(0));
462   //       neds->velocity()->setValue(1,neds->velocity()->getValue(1)+(VkcFNorm - VkFNorm)*FextNorm->getValue(1));
463   //       neds->velocity()->setValue(2,neds->velocity()->getValue(2)+(VkcFNorm - VkFNorm)*FextNorm->getValue(2));
464   // DEBUG_EXPR_WE(
465   //       std::cout<<"TimeSteppingDirectProjection::newtonSolve velocity updated\n";
466   //       printf("VELOCITY2 ");
467   //       neds->velocity()->display();
468   // )
469   //     }
470   //     SP::SiconosMatrix T = neds->T();
471   //     SP::SiconosVector dotq = neds->dotq();
472   //     prod(*T,*neds->velocity(),*dotq,true);
473   //     if(!_allNSProblems->empty())
474   //     {
475   //       for(unsigned int level = _levelMinForOutput;
476   //           level < _levelMaxForOutput;
477   //           level++)
478   //         updateOutput(level);
479   //     }
480   //   }
481   //#endif
482 
483 }
484 
computeCriteria(bool * runningProjection)485 void TimeSteppingDirectProjection::computeCriteria(bool * runningProjection)
486 {
487 
488   SP::InteractionsGraph indexSet = _nsds->topology()->indexSet(_indexSetLevelForProjection);
489   InteractionsGraph::VIterator aVi, viend;
490 
491   double maxViolationEquality = -1e24;
492   double minViolationEquality = +1e24;
493   double maxViolationUnilateral = -1e24;
494   //double minViolationUnilateral = +1e24;
495 
496   *runningProjection = false;
497 
498   for(std::tie(aVi, viend) = indexSet->vertices();
499       aVi != viend; ++aVi)
500   {
501     SP::Interaction inter = indexSet->bundle(*aVi);
502     inter->computeOutput(getTkp1(), 0);
503     inter->relation()->computeJach(getTkp1(), *inter);
504 
505     if(Type::value(*(inter->nonSmoothLaw())) ==  Type::NewtonImpactFrictionNSL ||
506         Type::value(*(inter->nonSmoothLaw())) == Type::NewtonImpactNSL)
507     {
508       double criteria = std::max(0.0, - inter->y(0)->getValue(0));
509       DEBUG_PRINTF("Unilateral inter->y(0)->getValue(0) %e.\n", inter->y(0)->getValue(0));
510       if(criteria > maxViolationUnilateral) maxViolationUnilateral = criteria;
511       //if (criteria < minViolationUnilateral) minViolationUnilateral=criteria;
512       if(maxViolationUnilateral > _constraintTolUnilateral)
513       {
514         *runningProjection = true;
515 
516         DEBUG_PRINTF("TSProj newton criteria unilateral true %e.\n", criteria);
517       }
518     }
519     else
520     {
521       DEBUG_PRINTF("Equality inter->y(0)->normInf() %e.\n", inter->y(0)->normInf());
522       if(inter->y(0)->normInf()  > maxViolationEquality) maxViolationEquality = inter->y(0)->normInf() ;
523       if(inter->y(0)->normInf()  < minViolationEquality) minViolationEquality = inter->y(0)->normInf() ;
524       if(inter->y(0)->normInf() > _constraintTol)
525       {
526         *runningProjection = true;
527         DEBUG_PRINTF("TSProj  newton criteria equality true %e.\n", inter->y(0)->normInf());
528       }
529     }
530     _maxViolationUnilateral = maxViolationUnilateral;
531     _maxViolationEquality = maxViolationEquality;
532   }
533 
534   DEBUG_PRINT("TSProj newton min/max criteria projection\n");
535   DEBUG_EXPR(std::cout << "             runningProjection "  << std::boolalpha << *runningProjection << std::endl;);
536   DEBUG_PRINTF("              min criteria equality =  %e.\n", minViolationEquality);
537   DEBUG_PRINTF("              max criteria equality =  %e.\n", maxViolationEquality);
538   DEBUG_PRINTF("              max criteria unilateral =  %e.\n", maxViolationUnilateral);
539   //DEBUG_PRINTF("              min criteria unilateral =  %e.\n",minViolationUnilateral);
540 
541 }
542 
543 
544 
newtonSolve(double criterion,unsigned int maxStep)545 void TimeSteppingDirectProjection::newtonSolve(double criterion, unsigned int maxStep)
546 {
547   bool isNewtonConverge = false;
548   _newtonNbIterations = 0; // number of Newton iterations
549   int info = 0;
550   //cout<<"||||||||||||||||||||||||||||||| ||||||||||||||||||||||||||||||| BEGIN NEWTON IT "<<endl;
551   bool isLinear  = _nsds->isLinear();
552   SP::InteractionsGraph indexSet = _nsds->topology()->indexSet(0);
553   initializeNewtonLoop();
554 
555   if((_newtonOptions == SICONOS_TS_LINEAR || _newtonOptions == SICONOS_TS_LINEAR_IMPLICIT)
556       || isLinear)
557   {
558     _newtonNbIterations++;
559     prepareNewtonIteration();
560     computeFreeState();
561     // updateOutput(0);
562     // updateIndexSets();
563     if(!_allNSProblems->empty() &&  indexSet->size()>0)
564       info = computeOneStepNSProblem(SICONOS_OSNSP_TS_VELOCITY);
565     // Check output from solver (convergence or not ...)
566     if(!checkSolverOutputProjectOnConstraints)
567       DefaultCheckSolverOutput(info);
568     else
569       checkSolverOutputProjectOnConstraints(info, this);
570 
571     update();
572 
573     //isNewtonConverge = newtonCheckConvergence(criterion);
574     if(!_allNSProblems->empty() &&   indexSet->size()>0)
575       saveYandLambdaInOldVariables();
576   }
577 
578   else if(_newtonOptions == SICONOS_TS_NONLINEAR)
579   {
580     while((!isNewtonConverge) && (_newtonNbIterations < maxStep) && (!info))
581     {
582       _newtonNbIterations++;
583       prepareNewtonIteration();
584       computeFreeState();
585       // updateOutput(0);
586       // updateIndexSets();
587 
588       // if there is not any Interaction at
589       // the beginning of the simulation _allNSProblems may not be
590       // empty here (check with SpaceFilter and one disk not on
591       // the ground : MultiBodyTest::t2)
592 
593       // if((*_allNSProblems)[SICONOS_OSNSP_TS_VELOCITY]->simulation())
594       // is also relevant here.
595       if(!_allNSProblems->empty() && indexSet->size()>0)
596       {
597         info = computeOneStepNSProblem(SICONOS_OSNSP_TS_VELOCITY);
598       }
599       // Check output from solver (convergence or not ...)
600       if(!checkSolverOutputProjectOnConstraints)
601         DefaultCheckSolverOutput(info);
602       else
603         checkSolverOutputProjectOnConstraints(info, this);
604 
605       updateInput();
606       updateState();
607       isNewtonConverge = newtonCheckConvergence(criterion);
608       if(!isNewtonConverge && !info)
609       {
610         updateOutput();
611         if(!_allNSProblems->empty() &&  indexSet->size()>0)
612           saveYandLambdaInOldVariables();
613       }
614     }
615     if(!isNewtonConverge)
616     {
617       if(_warnOnNonConvergence)
618       {
619         std::cout << "TimeStepping::newtonSolve -- Newton process stopped: max. number of steps (" << maxStep << ") reached." <<std::endl ;
620       }
621     }
622     else if(info && _warnOnNonConvergence)
623     {
624       std::cout << "TimeStepping::newtonSolve -- Newton process stopped: solver failed." <<std::endl ;
625     }
626     //    else
627     //      std::cout << "TimeStepping::newtonSolve succed nbit="<<_newtonNbIterations<<"maxStep="<<maxStep<<endl;
628   }
629   else
630     THROW_EXCEPTION("TimeStepping::NewtonSolve failed. Unknown newtonOptions: " + std::to_string(_newtonOptions));
631 }
632