1 // ============================================================================= 2 // PROJECT CHRONO - http://projectchrono.org 3 // 4 // Copyright (c) 2014 projectchrono.org 5 // All rights reserved. 6 // 7 // Use of this source code is governed by a BSD-style license that can be found 8 // in the LICENSE file at the top level of the distribution and at 9 // http://projectchrono.org/license-chrono.txt. 10 // 11 // ============================================================================= 12 // Authors: Alessandro Tasora, Radu Serban 13 // ============================================================================= 14 15 #ifndef CHINTEGRABLE_H 16 #define CHINTEGRABLE_H 17 18 #include <cstdlib> 19 20 #include "chrono/core/ChApiCE.h" 21 #include "chrono/core/ChMath.h" 22 #include "chrono/timestepper/ChState.h" 23 24 namespace chrono { 25 26 // ----------------------------------------------------------------------------- 27 28 /// Interface class for all objects that support time integration. 29 /// Derived concrete classes can use time integrators for the ChTimestepper hierarchy. 30 class ChApi ChIntegrable { 31 public: 32 /// Return the number of coordinates in the state Y. 33 virtual int GetNcoords_y() = 0; 34 35 /// Return the number of coordinates in the state increment. 36 /// This is a base implementation that works in many cases where dim(Y) = dim(dy), 37 /// but it can be overridden in the case that y contains quaternions for rotations 38 /// rather than simple y+dy GetNcoords_dy()39 virtual int GetNcoords_dy() { return GetNcoords_y(); } 40 41 /// Return the number of lagrangian multipliers (constraints). 42 /// By default returns 0. GetNconstr()43 virtual int GetNconstr() { return 0; } 44 45 /// Set up the system state. StateSetup(ChState & y,ChStateDelta & dy)46 virtual void StateSetup(ChState& y, ChStateDelta& dy) { 47 y.resize(GetNcoords_y()); 48 dy.resize(GetNcoords_dy()); 49 } 50 51 /// Gather system state in specified array. 52 /// Optionally, they will copy system private state, if any, to Y. StateGather(ChState & y,double & T)53 virtual void StateGather(ChState& y, double& T) {} 54 55 /// Scatter the states from the provided array to the system. 56 /// This function is called by time integrators every time they modify the Y state. 57 /// In some cases, the ChIntegrable object might contain dependent data structures 58 /// that might need an update at each change of Y. If so, this function must be overridden. StateScatter(const ChState & y,const double T,bool full_update)59 virtual void StateScatter(const ChState& y, const double T, bool full_update) {} 60 61 /// Gather from the system the state derivatives in specified array. 62 /// Optional: the integrable object might contain last computed state derivative, some integrators might reuse it. StateGatherDerivative(ChStateDelta & Dydt)63 virtual void StateGatherDerivative(ChStateDelta& Dydt) {} 64 65 /// Scatter the state derivatives from the provided array to the system. 66 /// Optional: the integrable object might need to store last computed state derivative, ex. for plotting etc. StateScatterDerivative(const ChStateDelta & Dydt)67 virtual void StateScatterDerivative(const ChStateDelta& Dydt) {} 68 69 /// Gather from the system the Lagrange multipliers in specified array. 70 /// Optional: the integrable object might contain Lagrange multipliers (reaction in constraints) StateGatherReactions(ChVectorDynamic<> & L)71 virtual void StateGatherReactions(ChVectorDynamic<>& L) {} 72 73 /// Scatter the Lagrange multipliers from the provided array to the system. 74 /// Optional: the integrable object might contain Lagrange multipliers (reaction in constraints) StateScatterReactions(const ChVectorDynamic<> & L)75 virtual void StateScatterReactions(const ChVectorDynamic<>& L) {} 76 77 /// Solve for state derivatives: dy/dt = f(y,t). 78 /// Given current state y , computes the state derivative dy/dt and Lagrange multipliers L (if any). 79 /// NOTE: some solvers (ex in DVI) cannot compute a classical derivative dy/dt when v is a function of 80 /// bounded variation, and f or L are distributions (e.g., when there are impulses and discontinuities), 81 /// so they compute a finite Dy through a finite dt. This is the reason why this function has an optional 82 /// parameter dt. In a DVI setting, one computes Dy, and returns Dy*(1/dt) here in Dydt parameter; if the 83 /// original Dy has to be known, just multiply Dydt*dt. The same for impulses: a DVI would compute 84 /// impulses I, and return L=I*(1/dt). 85 /// NOTES: 86 /// - derived classes must take care of calling StateScatter(y,T) before computing Dy, only if 87 /// force_state_scatter = true (otherwise it is assumed state is already in sync) 88 /// - derived classes must take care of resizing Dy and L if needed. 89 /// 90 /// This function must return true if successful and false otherwise. 91 virtual bool StateSolve(ChStateDelta& Dydt, ///< result: computed Dydt 92 ChVectorDynamic<>& L, ///< result: computed lagrangian multipliers, if any 93 const ChState& y, ///< current state y 94 const double T, ///< current time T 95 const double dt, ///< timestep (if needed, ex. in DVI) 96 bool force_state_scatter, ///< if false, y and T are not scattered to the system 97 bool full_update ///< if true, perform a full update during scatter 98 ) = 0; 99 100 /// Increment state array: y_new = y + Dy. 101 /// This is a base implementation that works in many cases, but it can be overridden 102 /// in the case that y contains quaternions for rotations, in which case rot. exponential is needed 103 /// instead of simply doing y+Dy. 104 /// NOTE: the system is not updated automatically after the state increment, so one might 105 /// need to call StateScatter(). 106 virtual void StateIncrement(ChState& y_new, ///< resulting y_new = y + Dy 107 const ChState& y, ///< initial state y 108 const ChStateDelta& Dy ///< state increment Dy 109 ); 110 111 // 112 // Functions required by implicit integration schemes 113 // 114 115 /// Assuming an explicit ODE 116 /// <pre> 117 /// H*dy/dt = F(y,t) 118 /// </pre> 119 /// or an explicit DAE 120 /// <pre> 121 /// H*dy/dt = F(y,t) + Cq*L 122 /// C(y,t) = 0 123 /// </pre> 124 /// this function must compute the state increment as required for a Newton iteration within an implicit integration 125 /// scheme. 126 /// For an ODE: 127 /// <pre> 128 /// Dy = [ c_a*H + c_b*dF/dy ]^-1 * R 129 /// Dy = [ G ]^-1 * R 130 /// </pre> 131 /// For a DAE with constraints: 132 /// <pre> 133 /// |Dy| = [ G Cq' ]^-1 * | R | 134 /// |DL| [ Cq 0 ] | Qc| 135 /// </pre> 136 /// where R is a given residual and dF/dy is the Jacobian of F. 137 /// 138 /// This function must return true if successful and false otherwise. StateSolveCorrection(ChStateDelta & Dy,ChVectorDynamic<> & L,const ChVectorDynamic<> & R,const ChVectorDynamic<> & Qc,const double a,const double b,const ChState & y,const double T,const double dt,bool force_state_scatter,bool full_update,bool force_setup)139 virtual bool StateSolveCorrection(ChStateDelta& Dy, ///< result: computed Dy 140 ChVectorDynamic<>& L, ///< result: computed lagrangian multipliers, if any 141 const ChVectorDynamic<>& R, ///< the R residual 142 const ChVectorDynamic<>& Qc, ///< the Qc residual 143 const double a, ///< the factor in c_a*H 144 const double b, ///< the factor in c_b*dF/dy 145 const ChState& y, ///< current state y 146 const double T, ///< current time T 147 const double dt, ///< timestep (if needed) 148 bool force_state_scatter, ///< if false, y is not scattered to the system 149 bool full_update, ///< if true, perform a full update during scatter 150 bool force_setup ///< if true, call the solver's Setup() function 151 ) { 152 throw ChException("StateSolveCorrection() not implemented, implicit integrators cannot be used. "); 153 } 154 155 /// Increment a vector R (usually the residual in a Newton Raphson iteration 156 /// for solving an implicit integration step) with a term that has H multiplied a given vector w: 157 /// R += c*H*w LoadResidual_Hv(ChVectorDynamic<> & R,const ChVectorDynamic<> & v,const double c)158 virtual void LoadResidual_Hv(ChVectorDynamic<>& R, ///< result: the R residual, R += c*M*v 159 const ChVectorDynamic<>& v, ///< the v vector 160 const double c ///< a scaling factor 161 ) { 162 throw ChException("LoadResidual_Hv() not implemented, implicit integrators cannot be used. "); 163 } 164 165 /// Increment a vector R (usually the residual in a Newton Raphson iteration 166 /// for solving an implicit integration step) with the term c*F: 167 /// R += c*F LoadResidual_F(ChVectorDynamic<> & R,const double c)168 virtual void LoadResidual_F(ChVectorDynamic<>& R, ///< result: the R residual, R += c*F 169 const double c ///< a scaling factor 170 ) { 171 throw ChException("LoadResidual_F() not implemented, implicit integrators cannot be used. "); 172 } 173 174 /// Increment a vector R (usually the residual in a Newton Raphson iteration 175 /// for solving an implicit integration step) with the term Cq'*L: 176 /// R += c*Cq'*L LoadResidual_CqL(ChVectorDynamic<> & R,const ChVectorDynamic<> & L,const double c)177 virtual void LoadResidual_CqL(ChVectorDynamic<>& R, ///< result: the R residual, R += c*Cq'*L 178 const ChVectorDynamic<>& L, ///< the L vector 179 const double c ///< a scaling factor 180 ) { 181 throw ChException("LoadResidual_CqL() not implemented, implicit integrators cannot be used. "); 182 } 183 184 /// Increment a vector Qc (usually the residual in a Newton Raphson iteration 185 /// for solving an implicit integration step, constraint part) with the term C: 186 /// Qc += c*C 187 virtual void LoadConstraint_C(ChVectorDynamic<>& Qc, ///< result: the Qc residual, Qc += c*C 188 const double c, ///< a scaling factor 189 const bool do_clamp = false, ///< enable optional clamping of Qc 190 const double mclam = 1e30 ///< clamping value 191 ) { 192 throw ChException("LoadConstraint_C() not implemented, implicit integrators cannot be used. "); 193 } 194 195 /// Increment a vector Qc (usually the residual in a Newton Raphson iteration 196 /// for solving an implicit integration step, constraint part) with the term Ct = partial derivative dC/dt: 197 /// Qc += c*Ct LoadConstraint_Ct(ChVectorDynamic<> & Qc,const double c)198 virtual void LoadConstraint_Ct(ChVectorDynamic<>& Qc, ///< result: the Qc residual, Qc += c*Ct 199 const double c ///< a scaling factor 200 ) { 201 throw ChException("LoadConstraint_Ct() not implemented, implicit integrators cannot be used. "); 202 } 203 }; 204 205 // ----------------------------------------------------------------------------- 206 207 /// Special subcase: II-order differential system. 208 /// Interface class for all objects that support time integration with state y that is second order: 209 /// y = {x, v} , dy/dt={v, a} 210 /// with positions x, speeds v=dx/dt, and accelerations a=ddx/dtdt. 211 /// Such systems permit the use of special integrators that can exploit the particular system structure. 212 class ChApi ChIntegrableIIorder : public ChIntegrable { 213 public: 214 /// Return the number of position coordinates x in y = {x, v} 215 virtual int GetNcoords_x() = 0; 216 217 /// Return the number of speed coordinates of v in y = {x, v} and dy/dt={v, a} 218 /// This is a base implementation that works in many cases where dim(v) = dim(x), but 219 /// might be less ex. if x uses quaternions and v uses angular vel. GetNcoords_v()220 virtual int GetNcoords_v() { return GetNcoords_x(); } 221 222 /// Return the number of acceleration coordinates of a in dy/dt={v, a} 223 /// This is a default implementation that works in almost all cases, as dim(a) = dim(v), GetNcoords_a()224 virtual int GetNcoords_a() { return GetNcoords_v(); } 225 226 /// Set up the system state with separate II order components x, v, a 227 /// for y = {x, v} and dy/dt={v, a} 228 virtual void StateSetup(ChState& x, ChStateDelta& v, ChStateDelta& a); 229 230 /// From system to state y={x,v} 231 /// Optionally, they will copy system private state, if any, to y={x,v} StateGather(ChState & x,ChStateDelta & v,double & T)232 virtual void StateGather(ChState& x, ChStateDelta& v, double& T) {} 233 234 /// Scatter the states from the provided arrays to the system. 235 /// This function is called by time integrators all times they modify the Y state. 236 /// In some cases, the ChIntegrable object might contain dependent data structures 237 /// that might need an update at each change of Y. If so, this function must be overridden. StateScatter(const ChState & x,const ChStateDelta & v,const double T,bool full_update)238 virtual void StateScatter(const ChState& x, const ChStateDelta& v, const double T, bool full_update) {} 239 240 /// Gather from the system the acceleration in specified array. 241 /// Optional: the integrable object might contain last computed state derivative, some integrators might use it. StateGatherAcceleration(ChStateDelta & a)242 virtual void StateGatherAcceleration(ChStateDelta& a) {} 243 244 /// Scatter the acceleration from the provided array to the system. 245 /// Optional: the integrable object might contain last computed state derivative, some integrators might use it. StateScatterAcceleration(const ChStateDelta & a)246 virtual void StateScatterAcceleration(const ChStateDelta& a) {} 247 248 /// Solve for accelerations: a = f(x,v,t) 249 /// Given current state y={x,v} , computes acceleration a in the state derivative dy/dt={v,a} and 250 /// lagrangian multipliers L (if any). 251 /// NOTES 252 /// - some solvers (ex in DVI) cannot compute a classical derivative dy/dt when v is a function 253 /// of bounded variation, and f or L are distributions (e.g., when there are impulses and 254 /// discontinuities), so they compute a finite Dv through a finite dt. This is the reason why 255 /// this function has an optional parameter dt. In a DVI setting, one computes Dv, and returns 256 /// Dv*(1/dt) here in Dvdt parameter; if the original Dv has to be known, just multiply Dvdt*dt later. 257 /// The same for impulses: a DVI would compute impulses I, and return L=I*(1/dt). 258 /// - derived classes must take care of calling StateScatter(y,T) before computing Dy, only if 259 /// force_state_scatter = true (otherwise it is assumed state is already in sync) 260 /// - derived classes must take care of resizing Dv if needed. 261 /// 262 /// This function must return true if successful and false otherwise. 263 /// 264 /// This default implementation uses the same functions already used for implicit integration. 265 /// WARNING: this implementation avoids the computation of the analytical expression for Qc, but 266 /// at the cost of three StateScatter updates (always complete updates). 267 virtual bool StateSolveA(ChStateDelta& Dvdt, ///< result: computed a for a=dv/dt 268 ChVectorDynamic<>& L, ///< result: computed lagrangian multipliers, if any 269 const ChState& x, ///< current state, x 270 const ChStateDelta& v, ///< current state, v 271 const double T, ///< current time T 272 const double dt, ///< timestep (if needed) 273 bool force_state_scatter, ///< if false, x,v and T are not scattered to the system 274 bool full_update ///< if true, perform a full update during scatter 275 ); 276 277 /// Increment state array: x_new = x + dx for x in Y = {x, dx/dt} 278 /// This is a base implementation that works in many cases, but it can be overridden 279 /// in the case that x contains quaternions for rotations 280 /// NOTE: the system is not updated automatically after the state increment, so one might 281 /// need to call StateScatter() if needed. 282 virtual void StateIncrementX(ChState& x_new, ///< resulting x_new = x + Dx 283 const ChState& x, ///< initial state x 284 const ChStateDelta& Dx ///< state increment Dx 285 ); 286 287 // 288 // Functions required by implicit integration schemes 289 // 290 291 /// Assuming an explicit ODE in the form 292 /// <pre> 293 /// M*a = F(x,v,t) 294 /// </pre> 295 /// or an explicit DAE in the form 296 /// <pre> 297 /// M*a = F(x,v,t) + Cq'*L 298 /// C(x,t) = 0 299 /// </pre> 300 /// this function must compute the solution of the change Du (in a or v or x) for a Newton iteration within an 301 /// implicit integration scheme. 302 /// If in ODE case: <pre> 303 /// Du = [ c_a*M + c_v*dF/dv + c_x*dF/dx ]^-1 * R 304 /// Du = [ G ]^-1 * R 305 /// </pre> 306 /// If with DAE constraints: 307 /// <pre> 308 /// |Du| = [ G Cq' ]^-1 * | R | 309 /// |DL| [ Cq 0 ] | Qc| 310 /// </pre> 311 /// where R is a given residual, dF/dv and dF/dx, dF/dv are jacobians (that are also 312 /// -R and -K, damping and stiffness (tangent) matrices in many mechanical problems, note the minus sign!). 313 /// It is up to the derived class how to solve such linear system. 314 /// 315 /// This function must return true if successful and false otherwise. StateSolveCorrection(ChStateDelta & Dv,ChVectorDynamic<> & L,const ChVectorDynamic<> & R,const ChVectorDynamic<> & Qc,const double c_a,const double c_v,const double c_x,const ChState & x,const ChStateDelta & v,const double T,bool force_state_scatter,bool full_update,bool force_setup)316 virtual bool StateSolveCorrection( 317 ChStateDelta& Dv, ///< result: computed Dv 318 ChVectorDynamic<>& L, ///< result: computed lagrangian multipliers, if any 319 const ChVectorDynamic<>& R, ///< the R residual 320 const ChVectorDynamic<>& Qc, ///< the Qc residual 321 const double c_a, ///< the factor in c_a*M 322 const double c_v, ///< the factor in c_v*dF/dv 323 const double c_x, ///< the factor in c_x*dF/dv 324 const ChState& x, ///< current state, x part 325 const ChStateDelta& v, ///< current state, v part 326 const double T, ///< current time T 327 bool force_state_scatter, ///< if false, x and v are not scattered to the system 328 bool full_update, ///< if true, perform a full update during scatter 329 bool force_setup ///< if true, call the solver's Setup() function 330 ) { 331 throw ChException("StateSolveCorrection() not implemented, implicit integrators cannot be used. "); 332 } 333 334 /// Assuming M*a = F(x,v,t) + Cq'*L 335 /// C(x,t) = 0 336 /// increment a vector R (usually the residual in a Newton Raphson iteration 337 /// for solving an implicit integration step) with the term c*F: 338 /// R += c*F LoadResidual_F(ChVectorDynamic<> & R,const double c)339 virtual void LoadResidual_F(ChVectorDynamic<>& R, ///< result: the R residual, R += c*F 340 const double c ///< a scaling factor 341 ) override { 342 throw ChException("LoadResidual_F() not implemented, implicit integrators cannot be used. "); 343 } 344 345 /// Assuming M*a = F(x,v,t) + Cq'*L 346 /// C(x,t) = 0 347 /// increment a vector R (usually the residual in a Newton Raphson iteration 348 /// for solving an implicit integration step) with a term that has M multiplied a given vector w: 349 /// R += c*M*w LoadResidual_Mv(ChVectorDynamic<> & R,const ChVectorDynamic<> & w,const double c)350 virtual void LoadResidual_Mv(ChVectorDynamic<>& R, ///< result: the R residual, R += c*M*v 351 const ChVectorDynamic<>& w, ///< the w vector 352 const double c ///< a scaling factor 353 ) { 354 throw ChException("LoadResidual_Mv() not implemented, implicit integrators cannot be used. "); 355 } 356 357 /// Assuming M*a = F(x,v,t) + Cq'*L 358 /// C(x,t) = 0 359 /// increment a vectorR (usually the residual in a Newton Raphson iteration 360 /// for solving an implicit integration step) with the term Cq'*L: 361 /// R += c*Cq'*L LoadResidual_CqL(ChVectorDynamic<> & R,const ChVectorDynamic<> & L,const double c)362 virtual void LoadResidual_CqL(ChVectorDynamic<>& R, ///< result: the R residual, R += c*Cq'*L 363 const ChVectorDynamic<>& L, ///< the L vector 364 const double c ///< a scaling factor 365 ) override { 366 throw ChException("LoadResidual_CqL() not implemented, implicit integrators cannot be used. "); 367 } 368 369 /// Assuming M*a = F(x,v,t) + Cq'*L 370 /// C(x,t) = 0 371 /// Increment a vector Qc (usually the residual in a Newton Raphson iteration 372 /// for solving an implicit integration step, constraint part) with the term C: 373 /// Qc += c*C 374 virtual void LoadConstraint_C(ChVectorDynamic<>& Qc, ///< result: the Qc residual, Qc += c*C 375 const double c, ///< a scaling factor 376 const bool do_clamp = false, ///< enable optional clamping of Qc 377 const double mclam = 1e30 ///< clamping value 378 ) override { 379 throw ChException("LoadConstraint_C() not implemented, implicit integrators cannot be used. "); 380 } 381 382 /// Assuming M*a = F(x,v,t) + Cq'*L 383 /// C(x,t) = 0 384 /// Increment a vector Qc (usually the residual in a Newton Raphson iteration 385 /// for solving an implicit integration step, constraint part) with the term Ct = partial derivative dC/dt: 386 /// Qc += c*Ct LoadConstraint_Ct(ChVectorDynamic<> & Qc,const double c)387 virtual void LoadConstraint_Ct(ChVectorDynamic<>& Qc, ///< result: the Qc residual, Qc += c*Ct 388 const double c ///< a scaling factor 389 ) override { 390 throw ChException("LoadConstraint_Ct() not implemented, implicit integrators cannot be used. "); 391 } 392 393 // 394 // OVERRIDE ChIntegrable BASE MEMBERS TO SUPPORT 1st ORDER INTEGRATORS: 395 // 396 397 // The following functions override the members in the base ChIntegrable class 398 // using a default bookkeeping that allows you to use timesteppers for 1st 399 // order integration with this II order system. The trick is that 400 // the x and v state parts are assembled into y={x,y} as this is needed, 401 // and viceversa. Same for dy/dt={v,a}. 402 // NOTE: PERFORMANCE WARNING: this default bookkeeping requires temporary allocation 403 // and deallocation of temporary vectors and some copies. 404 // NOTE: performance penalty is not a big issue since one should try to use 405 // custom II order timesteppers if possible. 406 // NOTE: children classes does not need to override those default functions. 407 408 /// Return the number of coordinates in the state Y. 409 /// (overrides base - just a fallback to enable using with plain 1st order timesteppers) GetNcoords_y()410 virtual int GetNcoords_y() override { return GetNcoords_x() + GetNcoords_v(); } 411 412 /// Return the number of coordinates in the state increment. 413 /// (overrides base - just a fallback to enable using with plain 1st order timesteppers) GetNcoords_dy()414 virtual int GetNcoords_dy() override { return GetNcoords_v() + GetNcoords_a(); } 415 416 /// Gather system state in specified array. 417 /// (overrides base - just a fallback to enable using with plain 1st order timesteppers) 418 /// PERFORMANCE WARNING! temporary vectors allocated on heap. This is only to support 419 /// compatibility with 1st order integrators. 420 virtual void StateGather(ChState& y, double& T) override; 421 422 /// Scatter the states from the provided array to the system. 423 /// (overrides base - just a fallback to enable using with plain 1st order timesteppers) 424 /// PERFORMANCE WARNING! temporary vectors allocated on heap. This is only to support 425 /// compatibility with 1st order integrators. 426 virtual void StateScatter(const ChState& y, const double T, bool full_update) override; 427 428 /// Gather from the system the state derivatives in specified array. 429 /// The integrable object might contain last computed state derivative, some integrators might reuse it. 430 /// (overrides base - just a fallback to enable using with plain 1st order timesteppers) 431 /// PERFORMANCE WARNING! temporary vectors allocated on heap. This is only to support 432 /// compatibility with 1st order integrators. 433 virtual void StateGatherDerivative(ChStateDelta& Dydt) override; 434 435 /// Scatter the state derivatives from the provided array to the system. 436 /// The integrable object might need to store last computed state derivative, ex. for plotting etc. 437 /// NOTE! the velocity in dsdt={v,a} is not scattered to the II order integrable, only acceleration is scattered! 438 /// (overrides base - just a fallback to enable using with plain 1st order timesteppers) 439 /// PERFORMANCE WARNING! temporary vectors allocated on heap. This is only to support 440 /// compatibility with 1st order integrators. 441 virtual void StateScatterDerivative(const ChStateDelta& Dydt) override; 442 443 /// Increment state array: y_new = y + Dy. 444 /// This is a base implementation that works in many cases. 445 /// It calls StateIncrementX() if used on x in y={x, dx/dt}. 446 /// It calls StateIncrementX() for x, and a normal sum for dx/dt if used on y in y={x, dx/dt} 447 virtual void StateIncrement(ChState& y_new, ///< resulting y_new = y + Dy 448 const ChState& y, ///< initial state y 449 const ChStateDelta& Dy ///< state increment Dy 450 ) override; 451 452 /// Solve for state derivatives: dy/dt = f(y,t). 453 /// (overrides base - just a fallback to enable using with plain 1st order timesteppers) 454 /// PERFORMANCE WARNING! temporary vectors allocated on heap. This is only to support 455 /// compatibility with 1st order integrators. 456 virtual bool StateSolve(ChStateDelta& dydt, ///< result: computed dydt 457 ChVectorDynamic<>& L, ///< result: computed lagrangian multipliers, if any 458 const ChState& y, ///< current state y 459 const double T, ///< current time T 460 const double dt, ///< timestep (if needed, ex. in DVI) 461 bool force_state_scatter, ///< if false, y and T are not scattered to the system 462 bool full_update ///< if true, perform a full update during scatter 463 ) override; 464 465 /// Override of method for Ist order implicit integrators. 466 /// This is disabled here because implicit integrators for Ist order cannot be used for a IInd order system. StateSolveCorrection(ChStateDelta & Dy,ChVectorDynamic<> & L,const ChVectorDynamic<> & R,const ChVectorDynamic<> & Qc,const double a,const double b,const ChState & y,const double T,const double dt,bool force_state_scatter,bool full_update,bool force_setup)467 virtual bool StateSolveCorrection(ChStateDelta& Dy, 468 ChVectorDynamic<>& L, 469 const ChVectorDynamic<>& R, 470 const ChVectorDynamic<>& Qc, 471 const double a, 472 const double b, 473 const ChState& y, 474 const double T, 475 const double dt, 476 bool force_state_scatter, 477 bool full_update, 478 bool force_setup) override final { 479 throw ChException( 480 "StateSolveCorrection() not implemented for ChIntegrableIIorder, implicit integrators for Ist order cannot " 481 "be used. "); 482 } 483 484 private: 485 using ChIntegrable::StateSetup; 486 }; 487 488 // ----------------------------------------------------------------------------- 489 490 /// Custom operator "+" that takes care of incremental update of a state y by an increment Dy. 491 /// "y_new = y + Dy", invokes the specialized StateIncrement() in the ChIntegrable. If none is 492 /// provided, this defaults to a simple vector sum 493 inline ChState operator+(const ChState& y, const ChStateDelta& Dy) { 494 ChState result(y.size(), y.GetIntegrable()); 495 y.GetIntegrable()->StateIncrement(result, y, Dy); 496 return result; 497 } 498 inline ChState& operator+=(ChState& y, const ChStateDelta& Dy) { 499 ChState tmp_y(y); 500 y.GetIntegrable()->StateIncrement(y, tmp_y, Dy); 501 return y; 502 } 503 504 /// Custom operator "+" that takes care of incremental update of a state y by an increment Dy 505 /// "y_new = Dy + y", invokes the specialized StateIncrement() in the ChIntegrable. If none is 506 /// provided, this defaults to a simple vector sum 507 inline ChState operator+(const ChStateDelta& Dy, const ChState& y) { 508 ChState result(y.size(), y.GetIntegrable()); 509 y.GetIntegrable()->StateIncrement(result, y, Dy); 510 return result; 511 } 512 513 /// Custom operator "-" that takes care of incremental update of a state y by an increment Dy. 514 /// "y_new = y - Dy", invokes the specialized StateIncrement() in the ChIntegrable. If none is 515 /// provided, this defaults to a simple vector sum 516 inline ChState operator-(const ChState& y, const ChStateDelta& Dy) { 517 ChState result(y.size(), y.GetIntegrable()); 518 y.GetIntegrable()->StateIncrement(result, y, Dy*-1); 519 return result; 520 } 521 inline ChState& operator-=(ChState& y, const ChStateDelta& Dy) { 522 ChState tmp_y(y); 523 y.GetIntegrable()->StateIncrement(y, tmp_y, Dy*-1); 524 return y; 525 } 526 527 /// Custom operator "-" that takes care of incremental update of a state y by an increment Dy 528 /// "y_new = Dy - y", invokes the specialized StateIncrement() in the ChIntegrable. If none is 529 /// provided, this defaults to a simple vector sum 530 inline ChState operator-(const ChStateDelta& Dy, const ChState& y) { 531 ChState result(y.size(), y.GetIntegrable()); 532 y.GetIntegrable()->StateIncrement(result, y, Dy*-1); 533 return result; 534 } 535 } // end namespace chrono 536 537 #endif 538