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