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