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 /*! \file  MoreauJeanOSI.hpp */
20 
21 #ifndef MoreauJeanOSI_H
22 #define MoreauJeanOSI_H
23 
24 #include "OneStepIntegrator.hpp"
25 
26 #include <limits>
27 
28 const unsigned int MOREAUSTEPSINMEMORY = 1;
29 
30 /** One Step time Integrator, Moreau-Jean algorithm.
31  * This integrator is the work horse of the event--capturing time stepping schemes
32  * for mechanical systems.  It is mainly based on the pioneering works of M. Jean and
33  * J.J. Moreau for the time integration of mechanical systems
34  * with unilateral contact, impact and Coulomb's friction with \f$\theta\f$ scheme
35  *
36  * For the linear Lagrangian system, the scheme reads as
37  *
38  \rst
39 
40  .. math::
41     :nowrap:
42 
43     \begin{cases}
44      M (v_{k+1}-v_k)
45      + h K q_{k+\theta} + h C v_{k+\theta}     -   h F_{k+\theta} = p_{k+1} = G P_{k+1},\label{eq:MoreauTS-motion}\\[1mm]
46      q_{k+1} = q_{k} + h v_{k+\theta}, \quad \\[1mm]
47      U_{k+1} = G^\top\, v_{k+1}, \\[1mm]
48      \begin{array}{lcl}
49       0 \leq U^\alpha_{k+1} + e  U^\alpha_{k} \perp P^\alpha_{k+1}  \geq 0,& \quad&\alpha \in \mathcal I_1, \\[1mm]
50       P^\alpha_{k+1}  =0,&\quad& \alpha \in \mathcal I \setminus \mathcal I_1,
51     \end{array}
52     \end{cases}
53 
54  \endrst
55 
56  * with  \f$\theta \in [0,1]\f$. The index set \f$\mathcal I_1\f$ is the discrete equivalent
57  * to the rule that allows us to apply the Signorini  condition at the velocity level.
58  * In the numerical practice, we choose to define this set by
59  * \f{equation}{
60  *   \label{eq:index-set1}
61  *  \mathcal I_1 = \{\alpha \in \mathcal I \mid G^\top (q_{k} + h v_{k}) + w \leq 0\text{ and } U_k \leq 0 \}.
62  * \f}.
63  *
64  * For more details, we refer to
65  *
66  * M. Jean and J.J. Moreau. Dynamics in the presence of unilateral contacts and dry friction: a numerical approach.
67  * In G. Del Pietro and F. Maceri, editors, Unilateral problems in structural analysis.
68  * II, pages 151–196. CISM 304, Spinger Verlag, 1987.
69  *
70  * J.J. Moreau. Unilateral contact and dry friction in finite freedom dynamics.
71  * In J.J. Moreau and Panagiotopoulos P.D., editors, Nonsmooth Mechanics and Applications,
72  * number 302 in CISM, Courses and lectures, pages 1–82. CISM 302, Spinger Verlag, Wien- New York, 1988a.
73  *
74  * J.J. Moreau. Numerical aspects of the sweeping process.
75  * Computer Methods in Applied Mechanics and Engineering, 177:329–349, 1999.
76  *
77  * M. Jean. The non smooth contact dynamics method.
78  * Computer Methods in Applied Mechanics and Engineering, 177:235–257, 1999.
79  *
80  * and for a review :
81  *
82  * V. Acary and B. Brogliato. Numerical Methods for Nonsmooth Dynamical Systems:
83  * Applications in Mechanics and Electronics, volume 35 of Lecture Notes in
84  * Applied and Computational Mechanics. Springer Verlag, 2008.
85  *
86  *
87  * MoreauJeanOSI class is used to define some time-integrators methods for a
88  * list of dynamical systems. A MoreauJeanOSI instance is defined by the value
89  * of theta and the list of concerned dynamical systems.
90  *
91  * Each DynamicalSystem is associated to a SiconosMatrix, named "W", the "iteration" matrix"
92  * W matrices are initialized and computed in initializeIterationMatrixW and computeW. Depending on the DS type,
93  * they may depend on time t and DS state x.
94  *
95  * For mechanical systems, the implementation uses _p for storing the
96  * the input due to the nonsmooth law. This MoreauJeanOSI scheme assumes that the
97  * relative degree is two.
98  *
99  * For Lagrangian systems, the implementation uses _p[1] for storing the
100  * discrete impulse.
101  *
102  * Main functions:
103  *
104  * - computeFreeState(): computes xfree (or vfree), dynamical systems
105  *   state without taking non-smooth part into account \n
106  *
107  * - updateState(): computes x (q,v), the complete dynamical systems
108  *    states.
109  * See User's guide for details.
110  *
111  */
112 class MoreauJeanOSI : public OneStepIntegrator
113 {
114 protected:
115   /** serialization hooks
116   */
117   ACCEPT_SERIALIZATION(MoreauJeanOSI);
118 
119   /** theta-scheme parameter */
120   double _theta;
121 
122   /** A gamma parameter for the forecast of activation of constraints
123    * leap-frog estimation of the constraints
124    * $\tilde y_k =  y_k + \gamma * h * ydot $
125    */
126   double _gamma;
127 
128   /** a boolean to know if the gamma-parameter must be used or not
129    */
130   bool _useGamma;
131 
132   /** Constraint activation threshold
133    *
134    */
135   double _constraintActivationThreshold;
136 
137   /** a boolean to know if the parameter must be used or not
138    */
139   bool _useGammaForRelation;
140 
141   /** a boolean to force the evaluation of T in an explicit way
142    */
143   bool _explicitNewtonEulerDSOperators;
144 
145   /** a boolean to know if the matrix W is symmetric definite positive
146    */
147   bool _isWSymmetricDefinitePositive;
148 
149   /** nslaw effects
150    */
151   struct _NSLEffectOnFreeOutput;
152   friend struct _NSLEffectOnFreeOutput;
153 
154 public:
155 
156   enum MoreauJeanOSI_ds_workVector_id{RESIDU_FREE, VFREE, BUFFER, QTMP, WORK_LENGTH};
157 
158   enum MoreauJeanOSI_interaction_workVector_id{OSNSP_RHS,WORK_INTERACTION_LENGTH};
159 
160   enum MoreauJeanOSI_interaction_workBlockVector_id{xfree, BLOCK_WORK_LENGTH};
161 
162   /** constructor from theta value only
163    *  \param theta value for all linked DS (default = 0.5).
164    *  \param gamma value for all linked DS (default = NaN and gamma is not used).
165    */
166   MoreauJeanOSI(double theta = 0.5, double gamma = std::numeric_limits<double>::quiet_NaN());
167 
168   /** destructor
169    */
~MoreauJeanOSI()170   virtual ~MoreauJeanOSI() {};
171 
172   // --- GETTERS/SETTERS ---
173 
174   /** get the value of W corresponding to DynamicalSystem ds
175    * \param ds a pointer to DynamicalSystem, optional, default =
176    * nullptr. get W[0] in that case
177    *  \return SimpleMatrix
178    */
179   const SimpleMatrix getW(SP::DynamicalSystem ds = SP::DynamicalSystem());
180 
181   /** get W corresponding to DynamicalSystem ds
182    * \param ds a pointer to DynamicalSystem
183    * \return pointer to a SiconosMatrix
184    */
185   SP::SimpleMatrix W(SP::DynamicalSystem ds);
186 
isWSymmetricDefinitePositive() const187   inline bool isWSymmetricDefinitePositive() const
188   {
189     return _isWSymmetricDefinitePositive;
190   };
191 
setIsWSymmetricDefinitePositive(bool b)192   inline void setIsWSymmetricDefinitePositive(bool b)
193   {
194     _isWSymmetricDefinitePositive = b ;
195   };
196 
197   // -- WBoundaryConditions --
198 
199 
200   /** Get the value of WBoundaryConditions corresponding to DynamicalSystem ds
201    * \param ds a pointer to DynamicalSystem, optional, default =
202    * nullptr. get WBoundaryConditions[0] in that case
203    *  \return SimpleMatrix
204    */
205   const SimpleMatrix getWBoundaryConditions(SP::DynamicalSystem ds = SP::DynamicalSystem());
206 
207   /** get WBoundaryConditions corresponding to DynamicalSystem ds
208    * \param ds a pointer to DynamicalSystem, optional, default =
209    * nullptr. get WBoundaryConditions[0] in that case
210    * \return pointer to a SiconosMatrix
211    */
212   SP::SiconosMatrix WBoundaryConditions(SP::DynamicalSystem ds);
213 
214   // -- theta --
215 
216   /** get theta
217    *  \return a double
218    */
theta()219   inline double theta()
220   {
221     return _theta;
222   };
223 
224   /** set the value of theta
225    *  \param newTheta a double
226    */
setTheta(double newTheta)227   inline void setTheta(double newTheta)
228   {
229     _theta = newTheta;
230   };
231 
232   // -- gamma --
233 
234   /** get gamma
235    *  \return a double
236    */
gamma()237   inline double gamma()
238   {
239     return _gamma;
240   };
241 
242   /** set the value of gamma
243    *  \param newGamma a double
244    */
setGamma(double newGamma)245   inline void setGamma(double newGamma)
246   {
247     _gamma = newGamma;
248     _useGamma = true;
249   };
250 
251   // -- useGamma --
252 
253   /** get bool useGamma
254    *  \return a bool
255    */
useGamma()256   inline bool useGamma()
257   {
258     return _useGamma;
259   };
260 
261   /** set the Boolean to indicate that we use gamma
262    *  \param newUseGamma  a  Boolean variable
263    */
setUseGamma(bool newUseGamma)264   inline void setUseGamma(bool newUseGamma)
265   {
266     _useGamma = newUseGamma;
267   };
268 
269   /** get bool gammaForRelation for the relation
270    *  \return a Boolean
271    */
useGammaForRelation()272   inline bool useGammaForRelation()
273   {
274     return _useGammaForRelation;
275   };
276 
277   /** set the boolean to indicate that we use gamma for the relation
278    *  \param newUseGammaForRelation a Boolean
279    */
setUseGammaForRelation(bool newUseGammaForRelation)280   inline void setUseGammaForRelation(bool newUseGammaForRelation)
281   {
282     _useGammaForRelation = newUseGammaForRelation;
283     if(_useGammaForRelation) _useGamma = false;
284   };
285   /** set the constraint activation threshold */
setConstraintActivationThreshold(double v)286   inline void setConstraintActivationThreshold (double v)
287   {
288     _constraintActivationThreshold = v;
289   }
290 
291   /** get the constraint activation threshold */
constraintActivationThreshold()292   inline double constraintActivationThreshold ()
293   {
294     return _constraintActivationThreshold ;
295   }
296 
297   /** get boolean _explicitNewtonEulerDSOperators for the relation
298    *  \return a Boolean
299    */
explicitNewtonEulerDSOperators()300   inline bool explicitNewtonEulerDSOperators()
301   {
302     return _explicitNewtonEulerDSOperators;
303   };
304 
305   /** set the boolean to indicate that we use gamma for the relation
306    *  \param newExplicitNewtonEulerDSOperators a Boolean
307    */
setExplicitNewtonEulerDSOperators(bool newExplicitNewtonEulerDSOperators)308   inline void setExplicitNewtonEulerDSOperators(bool newExplicitNewtonEulerDSOperators)
309   {
310     _explicitNewtonEulerDSOperators = newExplicitNewtonEulerDSOperators;
311   };
312 
313   // --- OTHER FUNCTIONS ---
314 
315   /** initialization of the MoreauJeanOSI integrator; for linear time
316       invariant systems, we compute time invariant operator (example :
317       W)
318    */
319   //virtual void initialize(Model& m);
320 
321   /** Initialization process of the nonsmooth problems
322       linked to this OSI*/
323   virtual void initialize_nonsmooth_problems();
324 
325   /** initialization of the work vectors and matrices (properties) related to
326    *  one dynamical system on the graph and needed by the osi
327    * \param t time of initialization
328    * \param ds the dynamical system
329    */
330   void initializeWorkVectorsForDS( double t, SP::DynamicalSystem ds);
331 
332   /** initialization of the work vectors and matrices (properties) related to
333    *  one interaction on the graph and needed by the osi
334    * \param inter the interaction
335    * \param interProp the properties on the graph
336    * \param DSG the dynamical systems graph
337    */
338   virtual void initializeWorkVectorsForInteraction(Interaction &inter,
339                              InteractionProperties& interProp,
340                              DynamicalSystemsGraph & DSG);
341 
342   /** get the number of index sets required for the simulation
343    * \return unsigned int
344    */
numberOfIndexSets() const345   unsigned int numberOfIndexSets() const {return 2;};
346 
347   /** initialize iteration matrix W MoreauJeanOSI matrix at time t
348    *  \param time
349    *  \param ds a pointer to DynamicalSystem
350    */
351   void initializeIterationMatrixW(double time, SP::SecondOrderDS ds);
352 
353   /** compute W MoreauJeanOSI matrix at time t
354    *  \param time (double)
355    *  \param ds a  DynamicalSystem
356    *  \param W the result in W
357    */
358   void computeW(double time , SecondOrderDS& ds, SiconosMatrix& W);
359 
360   /** compute WBoundaryConditionsMap[ds] MoreauJeanOSI matrix at time t
361    *  \param ds a pointer to DynamicalSystem
362    *  \param WBoundaryConditions write the result in WBoundaryConditions
363    *  \param iteration_matrix the OSI iteration matrix (W)
364    */
365   void _computeWBoundaryConditions(SecondOrderDS& ds, SiconosMatrix& WBoundaryConditions, SiconosMatrix& iteration_matrix);
366 
367   /** initialize iteration matrix WBoundaryConditionsMap[ds] MoreauJeanOSI
368    *  \param ds a pointer to DynamicalSystem
369    *  \param dsv a descriptor of the ds on the graph (redundant)
370    */
371   void _initializeIterationMatrixWBoundaryConditions(SecondOrderDS& ds, const DynamicalSystemsGraph::VDescriptor& dsv);
372 
373   void applyBoundaryConditions(SecondOrderDS& d,  SiconosVector& residu,
374                                DynamicalSystemsGraph::VIterator dsi, double t,
375                                const SiconosVector & v);
376 
377   /** compute the initial state of the Newton loop.
378    */
379   void computeInitialNewtonState();
380 
381 
382   /** return the maximum of all norms for the "MoreauJeanOSI-discretized" residus of DS
383       \return a double
384    */
385   double computeResidu();
386 
387   /** Perform the integration of the dynamical systems linked to this integrator
388    *  without taking into account the nonsmooth input (_r or _p)
389    */
390   virtual void computeFreeState();
391 
392   /** integrates the Interaction linked to this integrator, without taking non-smooth effects into account
393    * \param vertex_inter vertex of the interaction graph
394    * \param osnsp pointer to OneStepNSProblem
395    */
396   virtual void computeFreeOutput(InteractionsGraph::VDescriptor& vertex_inter, OneStepNSProblem* osnsp);
397 
398   /** Apply the rule to one Interaction to know if it should be included in the IndexSet of level i
399    * \param inter the Interaction to test
400    * \param i level of the IndexSet
401    * \return Boolean
402    */
403   virtual bool addInteractionInIndexSet(SP::Interaction inter, unsigned int i);
404 
405   /** Apply the rule to one Interaction to know if it should be removed from the IndexSet of level i
406    * \param inter the Interaction to test
407    * \param i level of the IndexSet
408    * \return Boolean
409    */
410   virtual bool removeInteractionFromIndexSet(SP::Interaction inter, unsigned int i);
411 
412 
413   /** method to prepare the fist Newton iteration
414    *   \param time
415    */
416   void prepareNewtonIteration(double time);
417 
418 
419   /** integrate the system, between tinit and tend (->iout=true), with possible stop at tout (->iout=false)
420    *  \param tinit the initial time
421    *  \param tend the end time
422    *  \param tout the real end time
423    *  \param notUsed useless flag (for MoreauJeanOSI, used in LsodarOSI)
424    */
425   void integrate(double& tinit, double& tend, double& tout, int& notUsed);
426 
427   /** update the state of the dynamical systems
428       \param ds the dynamical to update
429    */
430   virtual void updatePosition(DynamicalSystem& ds);
431 
432   /** update the state of the dynamical systems
433    *  \param level the level of interest for the dynamics: not used at the time
434    */
435   virtual void updateState(const unsigned int level);
436 
437   /** Displays the data of the MoreauJeanOSI's integrator
438    */
439   void display();
440 
441   /** visitors hook
442   */
443   ACCEPT_STD_VISITORS();
444 
445 };
446 
447 #endif // MoreauJeanOSI_H
448