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 CHSYSTEM_H 16 #define CHSYSTEM_H 17 18 #include <cfloat> 19 #include <memory> 20 #include <cstdlib> 21 #include <cmath> 22 #include <cstring> 23 #include <iostream> 24 #include <list> 25 26 #include "chrono/collision/ChCollisionSystem.h" 27 #include "chrono/core/ChGlobal.h" 28 #include "chrono/core/ChLog.h" 29 #include "chrono/core/ChMath.h" 30 #include "chrono/core/ChTimer.h" 31 #include "chrono/parallel/ChOpenMP.h" 32 #include "chrono/physics/ChAssembly.h" 33 #include "chrono/physics/ChBodyAuxRef.h" 34 #include "chrono/physics/ChContactContainer.h" 35 #include "chrono/physics/ChLinksAll.h" 36 #include "chrono/solver/ChSystemDescriptor.h" 37 #include "chrono/timestepper/ChAssemblyAnalysis.h" 38 #include "chrono/solver/ChSolver.h" 39 #include "chrono/timestepper/ChIntegrable.h" 40 #include "chrono/timestepper/ChTimestepper.h" 41 #include "chrono/timestepper/ChTimestepperHHT.h" 42 #include "chrono/timestepper/ChStaticAnalysis.h" 43 44 namespace chrono { 45 46 /// Physical system. 47 /// 48 /// This class is used to represent a multibody physical system, 49 /// so it acts also as a database for most items involved in 50 /// simulations, most noticeably objects of ChBody and ChLink 51 /// classes, which are used to represent mechanisms. 52 /// 53 /// Moreover, it also owns some global settings and features, 54 /// like the gravity acceleration, the global time and so on. 55 /// 56 /// This object will be responsible of performing the entire 57 /// physical simulation (dynamics, kinematics, statics, etc.), 58 /// so you need at least one ChSystem object in your program, in 59 /// order to perform simulations (you'll insert rigid bodies and 60 /// links into it..) 61 /// 62 /// Note that this is an abstract class, in your code you must 63 /// create a system from one of the concrete classes: 64 /// @ref chrono::ChSystemNSC (for non-smooth contacts) or 65 /// @ref chrono::ChSystemSMC (for smooth 'penalty' contacts). 66 /// 67 /// Further info at the @ref simulation_system manual page. 68 69 class ChApi ChSystem : public ChIntegrableIIorder { 70 71 public: 72 /// Create a physical system. 73 ChSystem(); 74 75 /// Copy constructor 76 ChSystem(const ChSystem& other); 77 78 /// Destructor 79 virtual ~ChSystem(); 80 81 /// "Virtual" copy constructor. 82 /// Concrete derived classes must implement this. 83 virtual ChSystem* Clone() const = 0; 84 85 // 86 // PROPERTIES 87 // 88 89 /// Sets the time step used for integration (dynamical simulation). 90 /// The lower this value, the more precise the simulation. Usually, values 91 /// about 0.01 s are enough for simple simulations. It may be modified automatically 92 /// by integration methods, if they support automatic time adaption. SetStep(double m_step)93 void SetStep(double m_step) { 94 if (m_step > 0) 95 step = m_step; 96 } 97 /// Gets the current time step used for the integration (dynamical simulation). GetStep()98 double GetStep() const { return step; } 99 100 /// Sets the lower limit for time step (only needed if using 101 /// integration methods which support time step adaption). SetStepMin(double m_step_min)102 void SetStepMin(double m_step_min) { 103 if (m_step_min > 0.) 104 step_min = m_step_min; 105 } 106 /// Gets the lower limit for time step GetStepMin()107 double GetStepMin() const { return step_min; } 108 109 /// Sets the upper limit for time step (only needed if using 110 /// integration methods which support time step adaption). SetStepMax(double m_step_max)111 void SetStepMax(double m_step_max) { 112 if (m_step_max > step_min) 113 step_max = m_step_max; 114 } 115 /// Gets the upper limit for time step GetStepMax()116 double GetStepMax() const { return step_max; } 117 118 /// Set the method for time integration (time stepper type). 119 /// - Suggested for fast dynamics with hard (NSC) contacts: EULER_IMPLICIT_LINEARIZED 120 /// - Suggested for fast dynamics with hard (NSC) contacts and low inter-penetration: EULER_IMPLICIT_PROJECTED 121 /// - Suggested for finite element smooth dynamics: HHT, EULER_IMPLICIT_LINEARIZED 122 /// 123 /// *Notes*: 124 /// - for more advanced customization, use SetTimestepper() 125 /// - old methods ANITESCU and TASORA were replaced by EULER_IMPLICIT_LINEARIZED and EULER_IMPLICIT_PROJECTED, 126 /// respectively 127 void SetTimestepperType(ChTimestepper::Type type); 128 129 /// Get the current method for time integration (time stepper type). GetTimestepperType()130 ChTimestepper::Type GetTimestepperType() const { return timestepper->GetType(); } 131 132 /// Set the timestepper object to be used for time integration. SetTimestepper(std::shared_ptr<ChTimestepper> mstepper)133 void SetTimestepper(std::shared_ptr<ChTimestepper> mstepper) { timestepper = mstepper; } 134 135 /// Get the timestepper currently used for time integration GetTimestepper()136 std::shared_ptr<ChTimestepper> GetTimestepper() const { return timestepper; } 137 138 /// Sets outer iteration limit for assembly constraints. When trying to keep constraints together, 139 /// the iterative process is stopped if this max.number of iterations (or tolerance) is reached. SetMaxiter(int m_maxiter)140 void SetMaxiter(int m_maxiter) { maxiter = m_maxiter; } 141 /// Gets iteration limit for assembly constraints. GetMaxiter()142 int GetMaxiter() const { return maxiter; } 143 144 /// Change the default composition laws for contact surface materials 145 /// (coefficient of friction, cohesion, compliance, etc.) 146 virtual void SetMaterialCompositionStrategy(std::unique_ptr<ChMaterialCompositionStrategy>&& strategy); 147 148 /// Accessor for the current composition laws for contact surface material. GetMaterialCompositionStrategy()149 const ChMaterialCompositionStrategy& GetMaterialCompositionStrategy() const { return *composition_strategy; } 150 151 /// For elastic collisions, with objects that have nonzero 152 /// restitution coefficient: objects will rebounce only if their 153 /// relative colliding speed is above this threshold. Default 0.15 m/s. 154 /// If this is too low, aliasing problems can happen with small high frequency 155 /// rebounces, and settling to static stacking might be more difficult. SetMinBounceSpeed(double mval)156 void SetMinBounceSpeed(double mval) { min_bounce_speed = mval; } 157 158 /// Objects will rebounce only if their relative colliding speed is above this threshold. GetMinBounceSpeed()159 double GetMinBounceSpeed() const { return min_bounce_speed; } 160 161 /// For the default stepper, you can limit the speed of exiting from penetration 162 /// situations. Usually set a positive value, about 0.1 .. 2 . (as exiting speed, in m/s) SetMaxPenetrationRecoverySpeed(double mval)163 void SetMaxPenetrationRecoverySpeed(double mval) { max_penetration_recovery_speed = mval; } 164 165 /// Get the limit on the speed for exiting from penetration situations (for Anitescu stepper) GetMaxPenetrationRecoverySpeed()166 double GetMaxPenetrationRecoverySpeed() const { return max_penetration_recovery_speed; } 167 168 /// Attach a solver (derived from ChSolver) for use by this system. 169 virtual void SetSolver(std::shared_ptr<ChSolver> newsolver); 170 171 /// Access the solver currently associated with this system. 172 virtual std::shared_ptr<ChSolver> GetSolver(); 173 174 /// Choose the solver type, to be used for the simultaneous solution of the constraints 175 /// in dynamical simulations (as well as in kinematics, statics, etc.) 176 /// - Suggested solver for speed, but lower precision: PSOR 177 /// - Suggested solver for higher precision: BARZILAIBORWEIN or APGD 178 /// - For problems that involve a stiffness matrix: GMRES, MINRES 179 /// 180 /// *Notes*: 181 /// - This function is a shortcut, internally equivalent to a call to SetSolver(). 182 /// - Only a subset of available Chrono solvers can be set through this mechanism. 183 /// - Prefer explicitly creating a solver, setting solver parameters, and then attaching the solver with 184 /// SetSolver. 185 /// 186 /// \deprecated This function does not support all available Chrono solvers. Prefer using SetSolver. 187 void SetSolverType(ChSolver::Type type); 188 189 /// Gets the current solver type. GetSolverType()190 ChSolver::Type GetSolverType() const { return solver->GetType(); } 191 192 /// Set the maximum number of iterations, if using an iterative solver. 193 /// \deprecated Prefer using SetSolver and setting solver parameters directly. 194 void SetSolverMaxIterations(int max_iters); 195 196 /// Get the current maximum number of iterations, if using an iterative solver. 197 /// \deprecated Prefer using GetSolver and accessing solver statistics directly. 198 int GetSolverMaxIterations() const; 199 200 /// Set the solver tolerance threshold (used with iterative solvers only). 201 /// Note that the stopping criteria differs from solver to solver. 202 void SetSolverTolerance(double tolerance); 203 204 /// Get the current tolerance value (used with iterative solvers only). 205 double GetSolverTolerance() const; 206 207 /// Set a solver tolerance threshold at force level (default: not specified). 208 /// Specify this value **only** if solving the problem at velocity level (e.g. solving a DVI problem). 209 /// If this tolerance is specified, it is multiplied by the current integration stepsize and overwrites the current 210 /// solver tolerance. By default, this tolerance is invalid and hence the solver's own tolerance threshold is used. SetSolverForceTolerance(double tolerance)211 void SetSolverForceTolerance(double tolerance) { tol_force = tolerance; } 212 213 /// Get the current value of the force-level tolerance (used with iterative solvers only). GetSolverForceTolerance()214 double GetSolverForceTolerance() const { return tol_force; } 215 216 /// Instead of using the default 'system descriptor', you can create your own custom descriptor 217 /// (inherited from ChSystemDescriptor) and plug it into the system using this function. 218 void SetSystemDescriptor(std::shared_ptr<ChSystemDescriptor> newdescriptor); 219 220 /// Access directly the 'system descriptor'. GetSystemDescriptor()221 std::shared_ptr<ChSystemDescriptor> GetSystemDescriptor() { return descriptor; } 222 223 /// Set the G (gravity) acceleration vector, affecting all the bodies in the system. Set_G_acc(const ChVector<> & m_acc)224 void Set_G_acc(const ChVector<>& m_acc) { G_acc = m_acc; } 225 226 /// Get the G (gravity) acceleration vector affecting all the bodies in the system. Get_G_acc()227 const ChVector<>& Get_G_acc() const { return G_acc; } 228 229 /// Get the simulation time of this system. GetChTime()230 double GetChTime() const { return ch_time; } 231 232 /// Set (overwrite) the simulation time of this system. SetChTime(double time)233 void SetChTime(double time) { ch_time = time; } 234 235 /// Set the number of OpenMP threads used by Chrono itself, Eigen, and the collision detection system. 236 /// <pre> 237 /// num_threads_chrono - used in FEA (parallel evaluation of internal forces and Jacobians) and 238 /// in SCM deformable terrain calculations. 239 /// num_threads_collision - used in parallelization of collision detection (if applicable). 240 /// If passing 0, then num_threads_collision = num_threads_chrono. 241 /// num_threads_eigen - used in the Eigen sparse direct solvers and a few linear algebra operations. 242 /// Note that Eigen enables multi-threaded execution only under certain size conditions. 243 /// See the Eigen documentation. 244 /// If passing 0, then num_threads_eigen = num_threads_chrono. 245 /// By default (if this function is not called), the following values are used: 246 /// num_threads_chrono = omp_get_num_procs() 247 /// num_threads_collision = 1 248 /// num_threads_eigen = 1 249 /// </pre> 250 /// Note that a derived class may ignore some or all of these settings. 251 virtual void SetNumThreads(int num_threads_chrono, int num_threads_collision = 0, int num_threads_eigen = 0); 252 GetNumThreadsChrono()253 int GetNumThreadsChrono() const { return nthreads_chrono; } GetNumthreadsCollision()254 int GetNumthreadsCollision() const { return nthreads_collision; } GetNumthreadsEigen()255 int GetNumthreadsEigen() const { return nthreads_eigen; } 256 257 // 258 // DATABASE HANDLING 259 // 260 261 /// Get the underlying assembly containing all physics items. GetAssembly()262 const ChAssembly& GetAssembly() const { return assembly; } 263 264 /// Attach a body to the underlying assembly. 265 virtual void AddBody(std::shared_ptr<ChBody> body); 266 267 /// Attach a link to the underlying assembly. 268 virtual void AddLink(std::shared_ptr<ChLinkBase> link); 269 270 /// Attach a mesh to the underlying assembly. 271 virtual void AddMesh(std::shared_ptr<fea::ChMesh> mesh); 272 273 /// Attach a ChPhysicsItem object that is not a body, link, or mesh. 274 virtual void AddOtherPhysicsItem(std::shared_ptr<ChPhysicsItem> item); 275 276 /// Attach an arbitrary ChPhysicsItem (e.g. ChBody, ChParticles, ChLink, etc.) to the assembly. 277 /// It will take care of adding it to the proper list of bodies, links, meshes, or generic 278 /// physic item. (i.e. it calls AddBody(), AddLink(), AddMesh(), or AddOtherPhysicsItem()). 279 /// Note, you cannot call Add() during an Update (i.e. items like particle generators that 280 /// are already inserted in the assembly cannot call this) because not thread safe; instead, 281 /// use AddBatch(). 282 void Add(std::shared_ptr<ChPhysicsItem> item); 283 284 /// Items added in this way are added like in the Add() method, but not instantly, 285 /// they are simply queued in a batch of 'to add' items, that are added automatically 286 /// at the first Setup() call. This is thread safe. AddBatch(std::shared_ptr<ChPhysicsItem> item)287 void AddBatch(std::shared_ptr<ChPhysicsItem> item) { assembly.AddBatch(item); } 288 289 /// If some items are queued for addition in the assembly, using AddBatch(), this will 290 /// effectively add them and clean the batch. Called automatically at each Setup(). FlushBatch()291 void FlushBatch() { assembly.FlushBatch(); } 292 293 /// Remove a body from this assembly. RemoveBody(std::shared_ptr<ChBody> body)294 virtual void RemoveBody(std::shared_ptr<ChBody> body) { assembly.RemoveBody(body); } 295 296 /// Remove a link from this assembly. RemoveLink(std::shared_ptr<ChLinkBase> link)297 virtual void RemoveLink(std::shared_ptr<ChLinkBase> link) { assembly.RemoveLink(link); } 298 299 /// Remove a mesh from the assembly. RemoveMesh(std::shared_ptr<fea::ChMesh> mesh)300 virtual void RemoveMesh(std::shared_ptr<fea::ChMesh> mesh) { assembly.RemoveMesh(mesh); } 301 302 /// Remove a ChPhysicsItem object that is not a body or a link RemoveOtherPhysicsItem(std::shared_ptr<ChPhysicsItem> item)303 virtual void RemoveOtherPhysicsItem(std::shared_ptr<ChPhysicsItem> item) { assembly.RemoveOtherPhysicsItem(item); } 304 305 /// Remove arbitrary ChPhysicsItem that was added to the underlying assembly. 306 void Remove(std::shared_ptr<ChPhysicsItem> item); 307 308 /// Remove all bodies from the underlying assembly. RemoveAllBodies()309 void RemoveAllBodies() { assembly.RemoveAllBodies(); } 310 /// Remove all links from the underlying assembly. RemoveAllLinks()311 void RemoveAllLinks() { assembly.RemoveAllLinks(); } 312 /// Remove all meshes from the underlying assembly. RemoveAllMeshes()313 void RemoveAllMeshes() { assembly.RemoveAllMeshes(); } 314 /// Remove all physics items not in the body, link, or mesh lists. RemoveAllOtherPhysicsItems()315 void RemoveAllOtherPhysicsItems() { assembly.RemoveAllOtherPhysicsItems(); } 316 317 /// Get the list of bodies. Get_bodylist()318 const std::vector<std::shared_ptr<ChBody>>& Get_bodylist() const { return assembly.bodylist; } 319 /// Get the list of links. Get_linklist()320 const std::vector<std::shared_ptr<ChLinkBase>>& Get_linklist() const { return assembly.linklist; } 321 /// Get the list of meshes. Get_meshlist()322 const std::vector<std::shared_ptr<fea::ChMesh>>& Get_meshlist() const { return assembly.meshlist; } 323 /// Get the list of physics items that are not in the body or link lists. Get_otherphysicslist()324 const std::vector<std::shared_ptr<ChPhysicsItem>>& Get_otherphysicslist() const { 325 return assembly.otherphysicslist; 326 } 327 328 /// Search a body by its name. SearchBody(const char * name)329 std::shared_ptr<ChBody> SearchBody(const char* name) { return assembly.SearchBody(name); } 330 /// Search a link by its name. SearchLink(const char * name)331 std::shared_ptr<ChLinkBase> SearchLink(const char* name) { return assembly.SearchLink(name); } 332 /// Search a mesh by its name. SearchMesh(const char * name)333 std::shared_ptr<fea::ChMesh> SearchMesh(const char* name) { return assembly.SearchMesh(name); } 334 /// Search from other ChPhysics items (not bodies, links, or meshes) by name. SearchOtherPhysicsItem(const char * name)335 std::shared_ptr<ChPhysicsItem> SearchOtherPhysicsItem(const char* name) { 336 return assembly.SearchOtherPhysicsItem(name); 337 } 338 /// Search a marker by its name. SearchMarker(const char * name)339 std::shared_ptr<ChMarker> SearchMarker(const char* name) { return assembly.SearchMarker(name); } 340 /// Search an item (body, link or other ChPhysics items) by name. Search(const char * name)341 std::shared_ptr<ChPhysicsItem> Search(const char* name) { return assembly.Search(name); } 342 /// Search a body by its ID SearchBodyID(int bodyID)343 std::shared_ptr<ChBody> SearchBodyID(int bodyID) { return assembly.SearchBodyID(bodyID); } 344 /// Search a marker by its unique ID. SearchMarker(int markID)345 std::shared_ptr<ChMarker> SearchMarker(int markID) { return assembly.SearchMarker(markID); } 346 347 /// Get the number of active bodies (excluding those that are sleeping or are fixed to ground). GetNbodies()348 int GetNbodies() const { return assembly.GetNbodies(); } 349 /// Get the number of bodies that are in sleeping mode (excluding fixed bodies). GetNbodiesSleeping()350 int GetNbodiesSleeping() const { return assembly.GetNbodiesSleeping(); } 351 /// Get the number of bodies that are fixed to ground. GetNbodiesFixed()352 int GetNbodiesFixed() const { return assembly.GetNbodiesFixed(); } 353 /// Get the total number of bodies in the assembly, including the grounded and sleeping bodies. GetNbodiesTotal()354 int GetNbodiesTotal() const { return assembly.GetNbodiesTotal(); } 355 356 /// Get the number of links. GetNlinks()357 int GetNlinks() const { return assembly.GetNlinks(); } 358 359 /// Get the number of meshes. GetNmeshes()360 int GetNmeshes() const { return assembly.GetNmeshes(); } 361 362 /// Get the number of other physics items (other than bodies, links, or meshes). GetNphysicsItems()363 int GetNphysicsItems() const { return assembly.GetNphysicsItems(); } 364 365 /// Get the number of coordinates (considering 7 coords for rigid bodies because of the 4 dof of quaternions). GetNcoords()366 int GetNcoords() const { return ncoords; } 367 /// Get the number of degrees of freedom of the assembly. GetNdof()368 int GetNdof() const { return ndof; } 369 /// Get the number of scalar constraints added to the assembly, including constraints on quaternion norms. GetNdoc()370 int GetNdoc() const { return ndoc; } 371 /// Get the number of system variables (coordinates plus the constraint multipliers, in case of quaternions). GetNsysvars()372 int GetNsysvars() const { return nsysvars; } 373 /// Get the number of coordinates (considering 6 coords for rigid bodies, 3 transl.+3rot.) GetNcoords_w()374 int GetNcoords_w() const { return ncoords_w; } 375 /// Get the number of scalar constraints added to the assembly. GetNdoc_w()376 int GetNdoc_w() const { return ndoc_w; } 377 /// Get the number of scalar constraints added to the assembly (only bilaterals). GetNdoc_w_C()378 int GetNdoc_w_C() const { return ndoc_w_C; } 379 /// Get the number of scalar constraints added to the assembly (only unilaterals). GetNdoc_w_D()380 int GetNdoc_w_D() const { return ndoc_w_D; } 381 /// Get the number of system variables (coordinates plus the constraint multipliers). GetNsysvars_w()382 int GetNsysvars_w() const { return nsysvars_w; } 383 384 /// Get the number of scalar coordinates (ex. dim of position vector) GetDOF()385 int GetDOF() const { return GetNcoords(); } 386 /// Get the number of scalar coordinates of variables derivatives (ex. dim of speed vector) GetDOF_w()387 int GetDOF_w() const { return GetNcoords_w(); } 388 /// Get the number of scalar constraints, if any, in this item GetDOC()389 int GetDOC() const { return GetNdoc_w(); } 390 /// Get the number of scalar constraints, if any, in this item (only bilateral constr.) GetDOC_c()391 int GetDOC_c() const { return GetNdoc_w_C(); } 392 /// Get the number of scalar constraints, if any, in this item (only unilateral constr.) GetDOC_d()393 int GetDOC_d() const { return GetNdoc_w_D(); } 394 395 /// Write the hierarchy of contained bodies, markers, etc. in ASCII 396 /// readable form, mostly for debugging purposes. Level is the tab spacing at the left. 397 void ShowHierarchy(ChStreamOutAscii& m_file, int level = 0) const { assembly.ShowHierarchy(m_file, level); } 398 399 /// Removes all bodies/marker/forces/links/contacts, also resets timers and events. 400 void Clear(); 401 402 /// Return the contact method supported by this system. 403 /// Contactables (bodies, FEA nodes, FEA traiangles, etc.) added to this system must be compatible. 404 virtual ChContactMethod GetContactMethod() const = 0; 405 406 /// Create and return the pointer to a new body. 407 /// The body is consistent with the type of the collision system currently associated with this ChSystem. 408 /// Note that the body is *not* attached to this system. 409 virtual ChBody* NewBody(); 410 411 /// Create and return the pointer to a new body with auxiliary reference frame. 412 /// The body is consistent with the type of the collision system currently associated with this ChSystem. 413 /// Note that the body is *not* attached to this system. 414 virtual ChBodyAuxRef* NewBodyAuxRef(); 415 416 /// Given inserted markers and links, restores the 417 /// pointers of links to markers given the information 418 /// about the marker IDs. Will be made obsolete in future with new serialization systems. 419 void Reference_LM_byID(); 420 421 // 422 // STATISTICS 423 // 424 425 /// Gets the number of contacts. 426 int GetNcontacts(); 427 428 /// Return the time (in seconds) spent for computing the time step. GetTimerStep()429 virtual double GetTimerStep() const { return timer_step(); } 430 /// Return the time (in seconds) for time integration, within the time step. GetTimerAdvance()431 virtual double GetTimerAdvance() const { return timer_advance(); } 432 /// Return the time (in seconds) for the solver, within the time step. 433 /// Note that this time excludes any calls to the solver's Setup function. GetTimerLSsolve()434 virtual double GetTimerLSsolve() const { return timer_ls_solve(); } 435 /// Return the time (in seconds) for the solver Setup phase, within the time step. GetTimerLSsetup()436 virtual double GetTimerLSsetup() const { return timer_ls_setup(); } 437 /// Return the time (in seconds) for calculating/loading Jacobian information, within the time step. GetTimerJacobian()438 virtual double GetTimerJacobian() const { return timer_jacobian(); } 439 /// Return the time (in seconds) for runnning the collision detection step, within the time step. GetTimerCollision()440 virtual double GetTimerCollision() const { return timer_collision(); } 441 /// Return the time (in seconds) for system setup, within the time step. GetTimerSetup()442 virtual double GetTimerSetup() const { return timer_setup(); } 443 /// Return the time (in seconds) for updating auxiliary data, within the time step. GetTimerUpdate()444 virtual double GetTimerUpdate() const { return timer_update(); } 445 446 /// Return the time (in seconds) for broadphase collision detection, within the time step. GetTimerCollisionBroad()447 double GetTimerCollisionBroad() const { return collision_system->GetTimerCollisionBroad(); } 448 /// Return the time (in seconds) for narrowphase collision detection, within the time step. GetTimerCollisionNarrow()449 double GetTimerCollisionNarrow() const { return collision_system->GetTimerCollisionNarrow(); } 450 451 /// Resets the timers. ResetTimers()452 void ResetTimers() { 453 timer_step.reset(); 454 timer_advance.reset(); 455 timer_ls_solve.reset(); 456 timer_ls_setup.reset(); 457 timer_jacobian.reset(); 458 timer_collision.reset(); 459 timer_setup.reset(); 460 timer_update.reset(); 461 collision_system->ResetTimers(); 462 } 463 464 protected: 465 /// Pushes all ChConstraints and ChVariables contained in links, bodies, etc. into the system descriptor. 466 virtual void DescriptorPrepareInject(ChSystemDescriptor& mdescriptor); 467 468 // Note: SetupInitial need not be typically called by a user, so it is currently marked protected 469 // (as it may need to be called by derived classes) 470 471 /// Initial system setup before analysis. 472 /// This function performs an initial system setup, once system construction is completed and before an analysis. 473 void SetupInitial(); 474 475 /// Return the resultant applied force on the specified body. 476 /// This resultant force includes all external applied loads acting on the body (from gravity, loads, springs, 477 /// etc). However, this does *not* include any constraint forces. In particular, contact forces are not included if 478 /// using the NSC formulation, but are included when using the SMC formulation. 479 virtual ChVector<> GetBodyAppliedForce(ChBody* body); 480 481 /// Return the resultant applied torque on the specified body. 482 /// This resultant torque includes all external applied loads acting on the body (from gravity, loads, springs, 483 /// etc). However, this does *not* include any constraint forces. In particular, contact torques are not included if 484 /// using the NSC formulation, but are included when using the SMC formulation. 485 virtual ChVector<> GetBodyAppliedTorque(ChBody* body); 486 487 public: 488 /// Counts the number of bodies and links. 489 /// Computes the offsets of object states in the global state. Assumes that offset_x, offset_w, and offset_L are 490 /// already set as starting point for offsetting all the contained sub objects. 491 virtual void Setup(); 492 493 /// Updates all the auxiliary data and children of 494 /// bodies, forces, links, given their current state. 495 void Update(double mytime, bool update_assets = true); 496 497 /// Updates all the auxiliary data and children of bodies, forces, links, given their current state. 498 void Update(bool update_assets = true); 499 500 /// In normal usage, no system update is necessary at the beginning of a new dynamics step (since an update is 501 /// performed at the end of a step). However, this is not the case if external changes to the system are made. Most 502 /// such changes are discovered automatically (addition/removal of items, input of mesh loads). For special cases, 503 /// this function allows the user to trigger a system update at the beginning of the step immediately following this 504 /// call. 505 void ForceUpdate(); 506 507 void IntToDescriptor(const unsigned int off_v, 508 const ChStateDelta& v, 509 const ChVectorDynamic<>& R, 510 const unsigned int off_L, 511 const ChVectorDynamic<>& L, 512 const ChVectorDynamic<>& Qc); 513 void IntFromDescriptor(const unsigned int off_v, ChStateDelta& v, const unsigned int off_L, ChVectorDynamic<>& L); 514 515 void InjectVariables(ChSystemDescriptor& mdescriptor); 516 517 void InjectConstraints(ChSystemDescriptor& mdescriptor); 518 void ConstraintsLoadJacobians(); 519 520 void InjectKRMmatrices(ChSystemDescriptor& mdescriptor); 521 void KRMmatricesLoad(double Kfactor, double Rfactor, double Mfactor); 522 523 // Old bookkeeping system 524 void VariablesFbReset(); 525 void VariablesFbLoadForces(double factor = 1); 526 void VariablesQbLoadSpeed(); 527 void VariablesFbIncrementMq(); 528 void VariablesQbSetSpeed(double step = 0); 529 void VariablesQbIncrementPosition(double step); 530 void ConstraintsBiReset(); 531 void ConstraintsBiLoad_C(double factor = 1, double recovery_clamp = 0.1, bool do_clamp = false); 532 void ConstraintsBiLoad_Ct(double factor = 1); 533 void ConstraintsBiLoad_Qc(double factor = 1); 534 void ConstraintsFbLoadForces(double factor = 1); 535 void ConstraintsFetch_react(double factor = 1); 536 537 // 538 // TIMESTEPPER INTERFACE 539 // 540 541 /// Tells the number of position coordinates x in y = {x, v} GetNcoords_x()542 virtual int GetNcoords_x() override { return GetNcoords(); } 543 544 /// Tells the number of speed coordinates of v in y = {x, v} and dy/dt={v, a} GetNcoords_v()545 virtual int GetNcoords_v() override { return GetNcoords_w(); } 546 547 /// Tells the number of lagrangian multipliers (constraints) GetNconstr()548 virtual int GetNconstr() override { return GetNdoc_w(); } 549 550 /// From system to state y={x,v} 551 virtual void StateGather(ChState& x, ChStateDelta& v, double& T) override; 552 553 /// From state Y={x,v} to system. This also triggers an update operation. 554 virtual void StateScatter(const ChState& x, 555 const ChStateDelta& v, 556 const double T, 557 bool full_update) override; 558 559 /// From system to state derivative (acceleration), some timesteppers might need last computed accel. 560 virtual void StateGatherAcceleration(ChStateDelta& a) override; 561 562 /// From state derivative (acceleration) to system, sometimes might be needed 563 virtual void StateScatterAcceleration(const ChStateDelta& a) override; 564 565 /// From system to reaction forces (last computed) - some timestepper might need this 566 virtual void StateGatherReactions(ChVectorDynamic<>& L) override; 567 568 /// From reaction forces to system, ex. store last computed reactions in ChLink objects for plotting etc. 569 virtual void StateScatterReactions(const ChVectorDynamic<>& L) override; 570 571 /// Perform x_new = x + dx, for x in Y = {x, dx/dt}.\n 572 /// It takes care of the fact that x has quaternions, dx has angular vel etc. 573 /// NOTE: the system is not updated automatically after the state increment, so one might 574 /// need to call StateScatter() if needed. 575 virtual void StateIncrementX(ChState& x_new, ///< resulting x_new = x + Dx 576 const ChState& x, ///< initial state x 577 const ChStateDelta& Dx ///< state increment Dx 578 ) override; 579 580 /// Assuming a DAE of the form 581 /// <pre> 582 /// M*a = F(x,v,t) + Cq'*L 583 /// C(x,t) = 0 584 /// </pre> 585 /// this function computes the solution of the change Du (in a or v or x) for a Newton 586 /// iteration within an implicit integration scheme. 587 /// <pre> 588 /// |Du| = [ G Cq' ]^-1 * | R | 589 /// |DL| [ Cq 0 ] | Qc| 590 /// </pre> 591 /// for residual R and G = [ c_a*M + c_v*dF/dv + c_x*dF/dx ].\n 592 /// This function returns true if successful and false otherwise. 593 virtual bool StateSolveCorrection( 594 ChStateDelta& Dv, ///< result: computed Dv 595 ChVectorDynamic<>& L, ///< result: computed lagrangian multipliers, if any 596 const ChVectorDynamic<>& R, ///< the R residual 597 const ChVectorDynamic<>& Qc, ///< the Qc residual 598 const double c_a, ///< the factor in c_a*M 599 const double c_v, ///< the factor in c_v*dF/dv 600 const double c_x, ///< the factor in c_x*dF/dv 601 const ChState& x, ///< current state, x part 602 const ChStateDelta& v, ///< current state, v part 603 const double T, ///< current time T 604 bool force_state_scatter, ///< if false, x and v are not scattered to the system 605 bool full_update, ///< if true, perform a full update during scatter 606 bool force_setup ///< if true, call the solver's Setup() function 607 ) override; 608 609 /// Increment a vector R with the term c*F: 610 /// R += c*F 611 virtual void LoadResidual_F(ChVectorDynamic<>& R, ///< result: the R residual, R += c*F 612 const double c ///< a scaling factor 613 ) override; 614 615 /// Increment a vector R with a term that has M multiplied a given vector w: 616 /// R += c*M*w 617 virtual void LoadResidual_Mv(ChVectorDynamic<>& R, ///< result: the R residual, R += c*M*v 618 const ChVectorDynamic<>& w, ///< the w vector 619 const double c ///< a scaling factor 620 ) override; 621 622 /// Increment a vectorR with the term Cq'*L: 623 /// R += c*Cq'*L 624 virtual void LoadResidual_CqL(ChVectorDynamic<>& R, ///< result: the R residual, R += c*Cq'*L 625 const ChVectorDynamic<>& L, ///< the L vector 626 const double c ///< a scaling factor 627 ) override; 628 629 /// Increment a vector Qc with the term C: 630 /// Qc += c*C 631 virtual void LoadConstraint_C(ChVectorDynamic<>& Qc, ///< result: the Qc residual, Qc += c*C 632 const double c, ///< a scaling factor 633 const bool do_clamp = false, ///< enable optional clamping of Qc 634 const double clamp = 1e30 ///< clamping value 635 ) override; 636 637 /// Increment a vector Qc with the term Ct = partial derivative dC/dt: 638 /// Qc += c*Ct 639 virtual void LoadConstraint_Ct(ChVectorDynamic<>& Qc, ///< result: the Qc residual, Qc += c*Ct 640 const double c ///< a scaling factor 641 ) override; 642 643 // 644 // UTILITY FUNCTIONS 645 // 646 647 /// Executes custom processing at the end of step. By default it does nothing, 648 /// but if you inherit a special ChSystem you can implement this. CustomEndOfStep()649 virtual void CustomEndOfStep() {} 650 651 /// Perform the collision detection. 652 /// New contacts are inserted in the ChContactContainer object(s), and old ones are removed. 653 /// This is mostly called automatically by time integration. 654 double ComputeCollisions(); 655 656 /// Class to be used as a callback interface for user defined actions performed 657 /// at each collision detection step. For example, additional contact points can 658 /// be added to the underlying contact container. 659 class ChApi CustomCollisionCallback { 660 public: ~CustomCollisionCallback()661 virtual ~CustomCollisionCallback() {} OnCustomCollision(ChSystem * msys)662 virtual void OnCustomCollision(ChSystem* msys) {} 663 }; 664 665 /// Specify a callback object to be invoked at each collision detection step. 666 /// Multiple such callback objects can be registered with a system. If present, 667 /// their OnCustomCollision() method is invoked. 668 /// Use this if you want that some specific callback function is executed at each 669 /// collision detection step (ex. all the times that ComputeCollisions() is automatically 670 /// called by the integration method). For example some other collision engine could 671 /// add further contacts using this callback. 672 void RegisterCustomCollisionCallback(std::shared_ptr<CustomCollisionCallback> callback); 673 674 /// Remove the given collision callback from this system. 675 void UnregisterCustomCollisionCallback(std::shared_ptr<CustomCollisionCallback> callback); 676 677 /// Change the underlying collision detection system to the specified type. 678 /// By default, a ChSystem uses a Bullet-based collision detection engine 679 /// (collision::ChCollisionSystemType::BULLET). 680 virtual void SetCollisionSystemType(collision::ChCollisionSystemType type); 681 682 /// Change the underlying collision system. 683 /// By default, a ChSystem uses a Bullet-based collision detection engine. 684 virtual void SetCollisionSystem(std::shared_ptr<collision::ChCollisionSystem> newcollsystem); 685 686 /// Access the underlying collision system. 687 /// Usually this is not needed, as the collision system is automatically handled by the ChSystem. GetCollisionSystem()688 std::shared_ptr<collision::ChCollisionSystem> GetCollisionSystem() const { return collision_system; } 689 690 /// Change the underlying contact container given the specified type of the collision detection system. 691 /// Usually this is not needed, as the contact container is automatically handled by the ChSystem. 692 /// The default implementation is a no-op, since the default contact container for a ChSystem is suitable for all 693 /// types of supported collision detection systems. SetContactContainer(collision::ChCollisionSystemType type)694 virtual void SetContactContainer(collision::ChCollisionSystemType type) {} 695 696 /// Change the underlying contact container. 697 /// The contact container collects information from the underlying collision detection system required for contact 698 /// force generation. Usually this is not needed, as the contact container is automatically handled by the ChSystem. 699 /// Make sure the provided contact container is compatible with both the collision detection system and the contact 700 /// force formulation (NSC or SMC). 701 virtual void SetContactContainer(std::shared_ptr<ChContactContainer> contactcontainer); 702 703 /// Access the underlying contact container. 704 /// Usually this is not needed, as the contact container is automatically handled by the ChSystem. GetContactContainer()705 std::shared_ptr<ChContactContainer> GetContactContainer() const { return contact_container; } 706 707 /// Turn on this feature to let the system put to sleep the bodies whose 708 /// motion has almost come to a rest. This feature will allow faster simulation 709 /// of large scenarios for real-time purposes, but it will affect the precision! 710 /// This functionality can be turned off selectively for specific ChBodies. SetUseSleeping(bool ms)711 void SetUseSleeping(bool ms) { use_sleeping = ms; } 712 713 /// Tell if the system will put to sleep the bodies whose motion has almost come to a rest. GetUseSleeping()714 bool GetUseSleeping() const { return use_sleeping; } 715 716 private: 717 /// Put bodies to sleep if possible. Also awakens sleeping bodies, if needed. 718 /// Returns true if some body changed from sleep to no sleep or viceversa, 719 /// returns false if nothing changed. In the former case, also performs Setup() 720 /// because the sleeping policy changed the totalDOFs and offsets. 721 bool ManageSleepingBodies(); 722 723 /// Performs a single dynamical simulation step, according to 724 /// current values of: Y, time, step (and other minor settings) 725 /// Depending on the integration type, it switches to one of the following: 726 virtual bool Integrate_Y(); 727 728 public: 729 // ---- DYNAMICS 730 731 /// Advances the dynamical simulation for a single step, of length step_size. 732 /// This function is typically called many times in a loop in order to simulate up to a desired end time. 733 int DoStepDynamics(double step_size); 734 735 /// Performs integration until the m_endtime is exactly 736 /// reached, but current time step may be automatically "retouched" to 737 /// meet exactly the m_endtime after n steps. 738 /// Useful when you want to advance the simulation in a 739 /// simulations (3d modeling software etc.) which needs updates 740 /// of the screen at a fixed rate (ex.30th of second) while 741 /// the integration must use more steps. 742 bool DoFrameDynamics(double end_time); 743 744 /// Given the current state, the sw simulates the 745 /// dynamical behavior of the system, until the end 746 /// time is reached, repeating many steps (maybe the step size 747 /// will be automatically changed if the integrator method supports 748 /// step size adaption). 749 bool DoEntireDynamics(double end_time); 750 751 /// Like "DoEntireDynamics", but results are provided at uniform 752 /// steps "frame_step", using the DoFrameDynamics() many times. 753 bool DoEntireUniformDynamics(double end_time, double frame_step); 754 755 /// Return the total number of time steps taken so far. GetStepcount()756 size_t GetStepcount() const { return stepcount; } 757 758 /// Reset to 0 the total number of time steps. ResetStepcount()759 void ResetStepcount() { stepcount = 0; } 760 761 /// Return the number of calls to the solver's Solve() function. 762 /// This counter is reset at each timestep. GetSolverCallsCount()763 int GetSolverCallsCount() const { return solvecount; } 764 765 /// Return the number of calls to the solver's Setup() function. 766 /// This counter is reset at each timestep. GetSolverSetupCount()767 int GetSolverSetupCount() const { return setupcount; } 768 769 /// Set this to "true" to enable automatic saving of solver matrices at each time 770 /// step, for debugging purposes. Note that matrices will be saved in the 771 /// working directory of the exe, with format 0001_01_H.dat 0002_01_H.dat 772 /// (if the timestepper requires multiple solves, also 0001_01. 0001_02.. etc.) 773 /// The matrices being saved are: 774 /// dump_Z.dat has the assembled optimization matrix (Matlab sparse format) 775 /// dump_rhs.dat has the assembled RHS 776 /// dump_H.dat has usually H=M (mass), but could be also H=a*M+b*K+c*R or such. (Matlab sparse format) 777 /// dump_Cq.dat has the jacobians (Matlab sparse format) 778 /// dump_E.dat has the constr.compliance (Matlab sparse format) 779 /// dump_f.dat has the applied loads 780 /// dump_b.dat has the constraint rhs 781 /// as passed to the solver in the problem 782 /// <pre> 783 /// | H -Cq'|*|q|- | f|= |0| 784 /// | Cq -E | |l| |-b| |c| 785 /// </pre> 786 /// where l \f$\in Y, c \in Ny\f$, normal cone to Y 787 SetDumpSolverMatrices(bool md)788 void SetDumpSolverMatrices(bool md) { dump_matrices = md; } GetDumpSolverMatrices()789 bool GetDumpSolverMatrices() const { return dump_matrices; } 790 791 /// Dump the current M mass matrix, K damping matrix, R damping matrix, Cq constraint jacobian 792 /// matrix (at the current configuration). 793 /// These can be later used for linearized motion, modal analysis, buckling analysis, etc. 794 /// The name of the files will be [path]_M.dat [path]_K.dat [path]_R.dat [path]_Cq.dat 795 /// Might throw ChException if file can't be saved. 796 void DumpSystemMatrices(bool save_M, bool save_K, bool save_R, bool save_Cq, const char* path); 797 798 /// Compute the system-level mass matrix. 799 /// This function has a small overhead, because it must assembly the 800 /// sparse matrix -which is used only for the purpose of this function. 801 void GetMassMatrix(ChSparseMatrix* M); ///< fill this system mass matrix 802 803 /// Compute the system-level stiffness matrix, i.e. the jacobian -dF/dq where F are stiff loads. 804 /// Note that not all loads provide a jacobian, as this is optional in their implementation. 805 /// This function has a small overhead, because it must assembly the 806 /// sparse matrix -which is used only for the purpose of this function. 807 void GetStiffnessMatrix(ChSparseMatrix* K); ///< fill this system stiffness matrix 808 809 /// Compute the system-level damping matrix, i.e. the jacobian -dF/dv where F are stiff loads. 810 /// Note that not all loads provide a jacobian, as this is optional in their implementation. 811 /// This function has a small overhead, because it must assembly the 812 /// sparse matrix -which is used only for the purpose of this function. 813 void GetDampingMatrix(ChSparseMatrix* R); ///< fill this system damping matrix 814 815 /// Compute the system-level constraint jacobian matrix, i.e. the jacobian 816 /// Cq=-dC/dq where C are constraints (the lower left part of the KKT matrix). 817 /// This function has a small overhead, because it must assembly the 818 /// sparse matrix -which is used only for the purpose of this function. 819 void GetConstraintJacobianMatrix(ChSparseMatrix* Cq); ///< fill this system damping matrix 820 821 // ---- KINEMATICS 822 823 /// Advances the kinematic simulation for a single step of given length. 824 bool DoStepKinematics(double step_size); 825 826 /// Performs kinematics until the end time is exactly reached. 827 /// The current time step may be automatically adjusted to meet exactly the m_endtime after n steps. 828 bool DoFrameKinematics(double end_time); 829 830 /// Given the current state, this kinematic simulation satisfies all the constraints with the "DoStepKinematics" 831 /// procedure for each time step, from the current time to the end time. 832 bool DoEntireKinematics(double end_time); 833 834 // ---- CONSTRAINT ASSEMBLATION 835 836 /// Given the current time and state, attempt to satisfy all constraints, using 837 /// a Newton-Raphson iteration loop. Used iteratively in inverse kinematics. 838 /// Action can be one of AssemblyLevel::POSITION, AssemblyLevel::VELOCITY, or 839 /// AssemblyLevel::ACCELERATION (or a combination of these) 840 /// Returns true if no errors and false if an error occurred (impossible assembly?) 841 bool DoAssembly(int action); 842 843 /// Shortcut for full position/velocity/acceleration assembly. 844 bool DoFullAssembly(); 845 846 // ---- STATICS 847 848 /// Perform a generic static analysis. Low level API, where the user creates and configures a 849 /// ChStaticAnalysis-inherited object by his own. For ready-to-use analysis, use 850 /// DoStaticLinear, DoStaticNonLinear, DoStaticNonlinearRheonomic etc. instead. 851 bool DoStaticAnalysis(std::shared_ptr<ChStaticAnalysis> analysis); 852 853 /// Solve the position of static equilibrium (and the reactions). 854 /// This is a one-step only approach that solves the **linear** equilibrium. 855 /// Appropriate mostly for FEM problems with small deformations. 856 bool DoStaticLinear(); 857 858 /// Solve the position of static equilibrium (and the reactions). 859 /// This function solves the equilibrium for the nonlinear problem (large displacements). 860 /// This version uses a nonlinear static analysis solver with default parameters. 861 bool DoStaticNonlinear(int nsteps = 10, bool verbose = false); 862 863 /// Solve the position of static equilibrium (and the reactions). 864 /// This function solves the equilibrium for the nonlinear problem (large displacements), 865 /// but differently from DoStaticNonlinear, it considers rheonomic constraints (ex. ChLinkMotorRotationSpeed) 866 /// that can impose steady-state speeds&accelerations to the mechanism, ex. to generate centrifugal forces in turbine blades. 867 /// This version uses a nonlinear static analysis solver with default parameters. 868 bool DoStaticNonlinearRheonomic(int nsteps = 10, bool verbose = false, std::shared_ptr<ChStaticNonLinearRheonomicAnalysis::IterationCallback> mcallback = nullptr); 869 870 /// Finds the position of static equilibrium (and the reactions) starting from the current position. 871 /// Since a truncated iterative method is used, you may need to call this method multiple times in case of large 872 /// nonlinearities before coming to the precise static solution. 873 bool DoStaticRelaxing(int nsteps = 10); 874 875 // 876 // SERIALIZATION 877 // 878 879 /// Method to allow serialization of transient data to archives. 880 virtual void ArchiveOUT(ChArchiveOut& marchive); 881 882 /// Method to allow deserialization of transient data from archives. 883 virtual void ArchiveIN(ChArchiveIn& marchive); 884 885 /// Process a ".chr" binary file containing the full system object 886 /// hierarchy as exported -for example- by the R3D modeler, with chrono plug-in version, 887 /// or by using the FileWriteChR() function. 888 int FileProcessChR(ChStreamInBinary& m_file); 889 890 /// Write a ".chr" binary file containing the full system object 891 /// hierarchy (bodies, forces, links, etc.) (deprecated function - obsolete) 892 int FileWriteChR(ChStreamOutBinary& m_file); 893 894 protected: 895 ChAssembly assembly; 896 897 std::shared_ptr<ChContactContainer> contact_container; ///< the container of contacts 898 899 ChVector<> G_acc; ///< gravitational acceleration 900 901 bool is_initialized; ///< if false, an initial setup is required (i.e. a call to SetupInitial) 902 bool is_updated; ///< if false, a new update is required (i.e. a call to Update) 903 904 int ncoords; ///< number of scalar coordinates (including 4th dimension of quaternions) for all active bodies 905 int ndoc; ///< number of scalar constraints (including constr. on quaternions) 906 int nsysvars; ///< number of variables (coords+lagrangian mult.), i.e. = ncoords+ndoc for all active bodies 907 int ncoords_w; ///< number of scalar coordinates when using 3 rot. dof. per body; for all active bodies 908 int ndoc_w; ///< number of scalar constraints when using 3 rot. dof. per body; for all active bodies 909 int nsysvars_w; ///< number of variables when using 3 rot. dof. per body; i.e. = ncoords_w+ndoc_w 910 int ndof; ///< number of degrees of freedom, = ncoords-ndoc = ncoords_w-ndoc_w , 911 int ndoc_w_C; ///< number of scalar constraints C, when using 3 rot. dof. per body (excluding unilaterals) 912 int ndoc_w_D; ///< number of scalar constraints D, when using 3 rot. dof. per body (only unilaterals) 913 914 double ch_time; ///< simulation time of the system 915 double step; ///< time step 916 double step_min; ///< min time step 917 double step_max; ///< max time step 918 919 double tol_force; ///< tolerance for forces (used to obtain a tolerance for impulses) 920 921 int maxiter; ///< max iterations for nonlinear convergence in DoAssembly() 922 923 bool use_sleeping; ///< if true, put to sleep objects that come to rest 924 925 std::shared_ptr<ChSystemDescriptor> descriptor; ///< system descriptor 926 std::shared_ptr<ChSolver> solver; ///< solver for DVI or DAE problem 927 928 double min_bounce_speed; ///< minimum speed for rebounce after impacts. Lower speeds are clamped to 0 929 double max_penetration_recovery_speed; ///< limit for the speed of penetration recovery (positive, speed of exiting) 930 931 size_t stepcount; ///< internal counter for steps 932 933 int setupcount; ///< number of calls to the solver's Setup() 934 int solvecount; ///< number of StateSolveCorrection (reset to 0 at each timestep of static analysis) 935 936 bool dump_matrices; ///< for debugging 937 938 int ncontacts; ///< total number of contacts 939 940 collision::ChCollisionSystemType collision_system_type; ///< type of the collision engine 941 std::shared_ptr<collision::ChCollisionSystem> collision_system; ///< collision engine 942 std::vector<std::shared_ptr<CustomCollisionCallback>> collision_callbacks; ///< user-defined collision callbacks 943 std::unique_ptr<ChMaterialCompositionStrategy> composition_strategy; /// material composition strategy 944 945 // OpenMP 946 int nthreads_chrono; 947 int nthreads_eigen; 948 int nthreads_collision; 949 950 // timers for profiling execution speed 951 ChTimer<double> timer_step; ///< timer for integration step 952 ChTimer<double> timer_advance; ///< timer for time integration 953 ChTimer<double> timer_ls_solve; ///< timer for solver (excluding setup phase) 954 ChTimer<double> timer_ls_setup; ///< timer for solver setup 955 ChTimer<double> timer_jacobian; ///< timer for computing/loading Jacobian information 956 ChTimer<double> timer_collision; ///< timer for collision detection 957 ChTimer<double> timer_setup; ///< timer for system setup 958 ChTimer<double> timer_update; ///< timer for system update 959 960 std::shared_ptr<ChTimestepper> timestepper; ///< time-stepper object 961 962 bool last_err; ///< indicates error over the last kinematic/dynamics/statics 963 964 ChVectorDynamic<> applied_forces; ///< system-wide vector of applied forces (lazy evaluation) 965 bool applied_forces_current; ///< indicates if system-wide vector of forces is up-to-date 966 967 // Friend class declarations 968 969 friend class ChAssembly; 970 friend class ChBody; 971 friend class fea::ChMesh; 972 973 friend class ChContactContainerNSC; 974 friend class ChContactContainerSMC; 975 }; 976 977 CH_CLASS_VERSION(ChSystem, 0) 978 979 } // end namespace chrono 980 981 #endif 982