GranOO  3.0
A robust and versatile workbench to build 3D dynamic simulations based on the Discrete Element Method
Standard.hpp
Go to the documentation of this file.
1 // This file is part of GranOO, a workbench for DEM simulation.
2 //
3 // Author(s) : - Damien Andre IRCER/UNILIM, Limoges France
4 // <damien.andre@unilim.fr>
5 // - Jean-luc Charles Arts et Metiers ParisTech, CNRS, I2M, Bordeaux France
6 // <jean-luc.charles@ensam.eu>
7 // - Jeremie Girardot Arts et Metiers ParisTech, CNRS, I2M, Bordeaux France
8 // <jeremie.girardot@ensam.eu>
9 // - Cedric Hubert LAMIH/UPHF, Valenciennes France
10 // <cedric.hubert@uphf.fr>
11 // - Ivan Iordanoff Arts et Metiers ParisTech, CNRS, I2M, Bordeaux France
12 // <ivan.iordanoff@ensam.eu>
13 //
14 // Copyright (C) 2008-2019 D. Andre, JL. Charles, J. Girardot, C. Hubert, I. Iordanoff
15 //
16 // This program is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 // This program is distributed in the hope that it will be useful,
22 // but WITHOUT ANY WARRANTY; without even the implied warranty of
23 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 // GNU General Public License for more details.
25 //
26 // You should have received a copy of the GNU General Public License
27 // along with this program. If not, see <http://www.gnu.org/licenses/>.
28 
29 
30 #ifndef _libDEM_ContactLaw_Standard_hpp_
31 #define _libDEM_ContactLaw_Standard_hpp_
32 
33 
35 
38 #include "GranOO3/DEM/Bond.hpp"
41 #include "GranOO3/DEM/Util/Formula.hpp"
43 #include "GranOO3/FEM/Surface.hpp"
44 
45 #include "GranOO3/Core/SetOf.hpp"
46 
48 
49 namespace GranOO3
50 {
51  namespace DEM
52  {
53 
54  template <class T>
55  class ContactLaw_Standard : public ContactLaw<T>
56  {
57 
58  GRANOO_OBJECT_FACTORY(ContactLaw_Standard);
59 
60  public:
61  static std::string class_ID() {return "Standard";}
62 
63  public:
64  //CONSTRUCTORS & DESTRUCTORS
66  virtual ~ContactLaw_Standard();
67 
68  //USEFULL
69  virtual void parse_xml();
70  virtual void compute_reaction(DEM::DiscreteElement& de1, T& de2, const Geom::Vector& normal, const double& penetration);
71  virtual double compute_critical_time_step() const;
72  virtual void info(std::ostream &) const;
73 
74  void set_stiffness(double);
75  void set_restitution_coeff(double);
76  void set_static_dry_friction_coeff(double);
77  void set_dynamic_dry_friction_coeff(double);
78  void set_dry_friction_slope(double);
79  void set_dry_friction_coeff(double);
80  void set_adhesion_force(double);
81 
82  double get_stiffness() const;
83  double get_restitution_coeff() const;
84  double get_static_dry_friction_coeff() const;
85  double get_dynamic_dry_friction_coeff() const;
86  double get_dry_friction_slope() const;
87  double get_dry_friction_coeff() const;
88  double get_adhesion_force() const;
89 
90  private:
93 
94  private:
96  double _stiffness;
102  double _dry_friction_coeff; //old version
103  std::string _regularization_type;
108  };
109 
110  template <> void
112 
113  template <class T> void
115  UserAssert(val >= 0., "The stiffness must be positive");
116  _stiffness = val;
117  }
118 
119  template <class T> void
121  UserAssert(val >= 0. && val <= 1.,
122  "The RestitutionCoeff must be between [0,1]");
123  _restitution_coeff = val;
124  _damping_factor = DEM::restitution_coeff_to_damping_factor(_restitution_coeff);
125  }
126 
127  template <class T> void
129  UserAssert(val >= 0. && val <= 1.,
130  "The StaticDryFrictionCoeff must be between [0,1]");
131  _static_dry_friction_coeff = val;
132  }
133 
134  template <class T> void
136  UserAssert(val >= 0. && val <= 1.,
137  "The DynamicDryFrictionCoeff must be between [0,1]");
138  _dynamic_dry_friction_coeff = val;
139  }
140 
141  template <class T> void
143  _dry_friction_slope = val;
144  }
145 
146  template <class T> void
148  _adhesion_force = val;
149  }
150 
151  template <class T> double
153  return _stiffness;
154  }
155 
156  template <class T> double
158  return _restitution_coeff;
159  }
160 
161  template <class T> double
163  return _dynamic_dry_friction_coeff;
164  }
165 
166  template <class T> double
168  return _dynamic_dry_friction_coeff;
169  }
170 
171  template <class T> double
173  return _dry_friction_slope;
174  }
175 
176  template <class T> double
178  return _adhesion_force;
179  }
180 
181  template <class T>
183  : ContactLaw<T>(),
184  _exclude_bonded_element(false),
185  _stiffness(0.),
186  _restitution_coeff(-1.),
187  _damping_factor(-1.),
188  _static_dry_friction_coeff(0.),
189  _dynamic_dry_friction_coeff(0.),
190  _dry_friction_slope(0),
191  _dry_friction_coeff(0),
192  _regularization_type(""),
193  _dry_friction_life_time(0.),
194  _adhesion_force(0.),
195  _normal_force(),
196  _normal_force_mode(false) {
198 
199  if (m.count("d") == false) {
200  double temp;
201  new Math::Variable("d", temp, "InterPenetration");
202  }
203  }
204 
205  template <class T>
207  }
208 
209  template <class T> void
212  parser.read_attribute(Attr::GRANOO_OPTIONAL, "Stiffness", _stiffness);
213 
214  std::string FnExpr = "";
215  parser.read_attribute(Attr::GRANOO_OPTIONAL, "NormalForce", FnExpr);
216 
217  parser.read_attribute(Attr::GRANOO_OPTIONAL, "RestitutionCoeff", _restitution_coeff);
218  parser.read_attribute(Attr::GRANOO_OPTIONAL, "damping_factor", _damping_factor);
219  parser.read_attribute(Attr::GRANOO_OPTIONAL, "ExcludeBondedDiscreteElements", _exclude_bonded_element);
220  parser.read_attribute(Attr::GRANOO_OPTIONAL, "StaticDryFrictionCoeff", _static_dry_friction_coeff);
221  parser.read_attribute(Attr::GRANOO_OPTIONAL, "DynamicDryFrictionCoeff", _dynamic_dry_friction_coeff);
222  parser.read_attribute(Attr::GRANOO_OPTIONAL, "DryFrictionSlope", _dry_friction_slope);
223  parser.read_attribute(Attr::GRANOO_OPTIONAL, "DryFrictionCoeff", _dry_friction_coeff);
224  parser.read_attribute(Attr::GRANOO_OPTIONAL, "RegularizationType", _regularization_type);
225  parser.read_attribute(Attr::GRANOO_OPTIONAL, "DryFrictionLifeTime", _dry_friction_life_time);
226  parser.read_attribute(Attr::GRANOO_OPTIONAL, "AdhesionForce", _adhesion_force);
227 
228  // manage the stifness or the normal force function
229  XmlAssert((_stiffness==0. && FnExpr!="") || (_stiffness>0. && FnExpr==""),
230  "You cannot use both Stiffness and NormalForce !");
231 
232  if (FnExpr!="") {
233  _normal_force_mode = true;
234  XmlAssert(_damping_factor==-1.,"Using the NormalForce, you cannot define a damping or restitution factor !");
235  XmlAssert(_restitution_coeff==-1.,"Using the NormalForce, you cannot define a damping or restitution factor !");
236 
237  if (FnExpr.find("d") == std::string::npos) // not necessary usefull
238  FnExpr += "*d";
239 
240  _normal_force.set(FnExpr);
241  }
242 
243 
244  // XmlAssert((_damping_factor == -1 && _restitution_coeff >= 0.) || (_damping_factor >= 0. && _restitution_coeff == -1),
245  // "You cannot use both RestitutionCoeff and damping_factor !");
246  XmlAssert(_restitution_coeff == -1 || (_restitution_coeff >= 0. && _restitution_coeff <= 1.),
247  "The RestitutionCoeff must be in [0, 1]");
248  XmlAssert(_damping_factor == -1 || (_damping_factor >= 0. && _damping_factor <= 1.),
249  "The damping_factor must be in [0, 1]");
250 
251  if (_restitution_coeff >= 0.) {
252  // if _restitution_coeff was given, compute _damping_factor:
253  _damping_factor = DEM::restitution_coeff_to_damping_factor(_restitution_coeff);
254  } else if (_damping_factor >= 0.) {
255  // _damping_factor_ was given, compute _restitution_coeff:
256  _restitution_coeff = DEM::damping_factor_To_restitution_coeff(_damping_factor);
257  }
258 
259 
260  XmlAssert(_regularization_type == "" || _regularization_type == "piecewise" || _regularization_type == "exponential",
261  "Available RegularizationTypes are 'piecewise' and 'exponential'");
262 
263  if (_regularization_type == "") {
264  XmlAssert(_dry_friction_coeff >= 0. && _dry_friction_slope >= 0, "A DryFrictionCoeff and a DryFrictionSlope are required.");
265  XmlAssert(_dry_friction_coeff >= 0. && _dry_friction_coeff <= 1, "The DryFrictionCoeff must be in range [0,1].");
266  XmlAssert(_dry_friction_slope >= 0, "The DryFrictionSlope must be positive.");
267  } else {
268  XmlAssert(_static_dry_friction_coeff >= 0. && _static_dry_friction_coeff <= 1., "The StaticDryFrictionCoeff must be in range [0,1].");
269  XmlAssert(_dynamic_dry_friction_coeff >= 0. && _dynamic_dry_friction_coeff <= 1., "The DynamicDryFrictionCoeff must be in range [0,1].");
270  if (_regularization_type == "piecewise")
271  XmlAssert(_dry_friction_slope >0, "Piecewise regularization requires a positive DryFrictionSlope");
272  if (_regularization_type == "exponential" )
273  XmlAssert(_dry_friction_life_time >0, "Exponential regularization requires a positive DryFrictionLifeTime");
274 
275  }
276  }
277 
278  template <class T> void
279  ContactLaw_Standard<T>::info(std::ostream & out) const {
280  out << "ContactLaw_Standard" << granoo::endl;
281  out << "\t stiffness : " << _stiffness << granoo::endl;
282  out << "\t restitutionCoeff : " << _restitution_coeff << granoo::endl;
283  out << "\t dampingFactor : " << _damping_factor << granoo::endl;
284  out << "\t regularizationType : " << _regularization_type << granoo::endl;
285  out << "\t staticDryFrictionCoeff : " << _static_dry_friction_coeff << granoo::endl;
286  out << "\t dynamicDryFrictionCoeff: " << _dynamic_dry_friction_coeff << granoo::endl;
287  out << "\t dryFrictionSlope : " << _dry_friction_slope << granoo::endl;
288  out << "\t dryFrictionCoeff : " << _dry_friction_coeff << granoo::endl;
289  out << "\t dryFrictionLifeTime : " << _dry_friction_life_time << granoo::endl;
290  out << "\t adhesionForce : " << _adhesion_force << granoo::endl;
291  }
292 
293  template <class T> double
295  // const double minMass = set.lightest().get_mass();
296  double minMass = std::numeric_limits<double>::max();
297 
299  for (unsigned int i = 0; i<set.size(); i++) {
300  minMass = set(i).get_mass() < minMass ? set(i).get_mass() : minMass;
301  }
302  return sqrt(minMass/get_stiffness());
303  }
304 
305  // contact between 1 DE and a phantom body
306  // -----------------------------------------------------------------
307 
308 
309  template <class T> void
311  T& de2,
312  const Geom::Vector& normal,
313  const double& penetration) {
314 
315  if (_exclude_bonded_element) {
316  DEM::Element* e1 = dynamic_cast<DEM::Element*>(&de1);
317  DEM::Element* e2 = dynamic_cast<DEM::Element*>(&de2);
318  if (e1->is_bonded(*e2))
319  return;
320  }
321 
322  SafeModeAssert(penetration >= 0, "The penetration between de1 and de2 must be positve");
323 
324  // Compute stiffness reaction
325  Geom::Vector Fn;
326  if (_normal_force_mode) {
327  Math::Variable::get("d").set_val(penetration);
328  Fn = normal*_normal_force.value();
329  } else
330  Fn = normal*_stiffness*penetration;
331 
332  APPLY_FORCE(Fn, -Fn, "[ContactLaw_Standard]_Elas");
333 
334  // Compute static and dynamic friction reaction
335  if (_static_dry_friction_coeff > 0. || _dynamic_dry_friction_coeff > 0. || _dry_friction_coeff > 0) {
336 
337  const Geom::Vector AO1 = -de1.get_radius()*normal;
338  const Geom::Vector O1O2 = de1.get_position() - de2.get_position();
339  const Geom::Vector AO2 = AO1+O1O2;
340  const Geom::Vector & V1 = de1.get_linear_velocity();
341  const Geom::Vector & V2 = de2.get_linear_velocity();
342  const Geom::Vector & W1 = de1.get_angular_velocity();
343  const Geom::Vector & W2 = de2.get_angular_velocity();
344  Geom::Vector Vrel = V1 + (AO1^W1) - V2 - (AO2^W2);
345  Vrel -= normal*(Vrel*normal); // relative velocity in tangential plan
346  const Geom::Vector tg = Vrel.unit(); // tangent direction vector
347 
348  double mu = 0;
349  const double VrelModulus = Vrel.norm();
350 
351  if (_regularization_type == "piecewise") {
352  // piecewise linear law for Coulomb Law regularization
353  if (VrelModulus < _static_dry_friction_coeff/_dry_friction_slope) {
354  mu = _dry_friction_slope*VrelModulus;
355  } else if ( (VrelModulus > (_static_dry_friction_coeff/_dry_friction_slope)) && (VrelModulus < ((2*_static_dry_friction_coeff-_dynamic_dry_friction_coeff)/_dry_friction_slope)) ) {
356  mu = _static_dry_friction_coeff - _dry_friction_slope*(VrelModulus - _static_dry_friction_coeff/_dry_friction_slope);
357  } else if (VrelModulus > ((2*_static_dry_friction_coeff-_dynamic_dry_friction_coeff)/_dry_friction_slope)) {
358  mu = _dynamic_dry_friction_coeff;
359  }
360  } else if (_regularization_type == "exponential") {
361  // Decreasing exponential law for Coulomb Law regularization
362  mu = _dynamic_dry_friction_coeff + (_static_dry_friction_coeff-_dynamic_dry_friction_coeff)*exp(-VrelModulus/_dry_friction_life_time);
363  } else {
364  // Old version
365  mu = (_dry_friction_slope*VrelModulus < _dry_friction_coeff ) ? _dry_friction_slope*VrelModulus : _dry_friction_coeff;
366  }
367 
368  Geom::Vector Ft = mu * Fn.norm() * tg;
369  APPLY_FORCE(-Ft, Ft, "[ContactLaw_Standard]_Fric");
370  APPLY_TORQUE(-(-AO1)^Ft, (-AO2)^Ft, "[ContactLaw_Standard]_Fric");
371  }
372 
373  // computes adhesion
374  if (_adhesion_force > 0.) {
375  const Geom::Vector Fa = _adhesion_force*normal;
376  APPLY_FORCE(Fa, -Fa, "[Contactlaw_Standard]_Adhe");
377  }
378 
379  // computes damping reaction
380  if (_restitution_coeff != 0.) {
381  const double M1 = de1.get_mass();
382  const double M2 = de2.get_mass();
383  const double M = M1*M2/(M1+M2);
384  const double K = _stiffness;
385  const double dampCoeff = 2.*_damping_factor*sqrt(K*M);
386  const double velocityDiff = (de2.get_linear_velocity() - de1.get_linear_velocity()) * normal;
387  const Geom::Vector Fd = dampCoeff * velocityDiff * normal;
388 
389  APPLY_FORCE(Fd, -Fd, "[ContactLaw_Standard]_Damp");
390  }
391  }
392 
393  template<> inline void
395  DEM::SupportShape& de2,
396  const Geom::Vector& normal,
397  const double& penetration) {
398  SafeModeAssert(penetration >= 0, "The penetration between de1 and de2 must be positve");
400 
401  // Compute stiffness reaction
402  Geom::Vector Fn;
403  if (_normal_force_mode) {
404  Math::Variable::get("d").set_val(penetration);
405  Fn = normal*_normal_force.value();
406  } else
407  Fn = normal*_stiffness*penetration;
408 
409  de.force() += Fn;
410  if (energyBalance.is_enable())
411  energyBalance.add_force_on(de, "[ContactLaw_Standard]_Elas", Fn);
412 
413  // Compute static and dynamic friction reaction
414  if (_static_dry_friction_coeff > 0. || _dynamic_dry_friction_coeff > 0. || _dry_friction_coeff > 0) {
415  const Geom::Vector AO1 = -de.get_radius()*normal;
416  const Geom::Vector O1O2 = de.get_position() - de2.get_position();
417  const Geom::Vector AO2 = AO1+O1O2;
418  const Geom::Vector & V1 = de.get_linear_velocity();
419  const Geom::Vector & V2 = de2.get_linear_velocity();
420  const Geom::Vector & W1 = de.get_angular_velocity();
421  const Geom::Vector & W2 = de2.get_angular_velocity();
422 
423  Geom::Vector Vrel = V1 + (AO1^W1) - V2 - (AO2^W2);
424  Vrel -= normal*(Vrel*normal); // relative velocity in tangential plan
425 
426  double mu = 0;
427  const double VrelModulus = Vrel.norm();
428 
429  if (_regularization_type == "piecewise") {
430  // piecewise linear law for Coulomb Law regularization
431  if (VrelModulus < _static_dry_friction_coeff/_dry_friction_slope) {
432  mu = _dry_friction_slope*VrelModulus;
433  } else if ( (VrelModulus > (_static_dry_friction_coeff/_dry_friction_slope)) &&
434  (VrelModulus < ((2*_static_dry_friction_coeff-_dynamic_dry_friction_coeff)/_dry_friction_slope)) ) {
435  mu = _static_dry_friction_coeff - _dry_friction_slope*(VrelModulus - _static_dry_friction_coeff/_dry_friction_slope);
436  } else if (VrelModulus > ((2*_static_dry_friction_coeff-_dynamic_dry_friction_coeff)/_dry_friction_slope)) {
437  mu = _dynamic_dry_friction_coeff;
438  }
439  } else if (_regularization_type == "exponential") {
440  // Decreasing exponential law for Coulomb Law regularization
441  mu = _dynamic_dry_friction_coeff + (_static_dry_friction_coeff-_dynamic_dry_friction_coeff)*exp(-VrelModulus*1e8);
442  } else {
443  // Old version
444  mu = (_dry_friction_slope*VrelModulus < _dry_friction_coeff ) ? _dry_friction_slope*VrelModulus : _dry_friction_coeff;
445  }
446 
447  Geom::Vector Ft = mu * Fn.norm() * Vrel.unit();
448 
449  de.force() -= Ft;
450  de.torque() -= (-AO1)^Ft;
451 
452  if (energyBalance.is_enable()) {
453  energyBalance.add_force_on (de, "[ContactLaw_Standard]_Fric", -Ft);
454  energyBalance.add_torque_on(de, "[ContactLaw_Standard]_Fric", AO1^Ft);
455  }
456  }
457 
458  // computes adhesion
459  if (_adhesion_force > 0.) {
460  const Geom::Vector Fa = _adhesion_force*normal;
461  de.force() += Fa;
462 
463  if (energyBalance.is_enable())
464  energyBalance.add_force_on(de, "[ContactLaw_Standard]_Adhe", Fa);
465  }
466 
467  // computes damping reaction
468  if (_restitution_coeff != 0.) {
469  const double M = de.get_mass();
470  const double K = _stiffness;
471  const double dampCoeff = 2.*_damping_factor*sqrt(K*M);
472  const double velocityDiff = -de.get_linear_velocity() * normal;
473  const Geom::Vector Fd = dampCoeff * velocityDiff * normal;
474  de.force() += Fd;
475 
476  if (energyBalance.is_enable())
477  energyBalance.add_force_on(de, "[ContactLaw_Standard]_Damp", Fd);
478  }
479  }
480 
481  }
482 }
483 
484 #endif
#define APPLY_TORQUE(T1, T2, energyLabel)
Definition: ContactLaw.hpp:52
#define APPLY_FORCE(F1, F2, energyLabel)
Definition: ContactLaw.hpp:39
#define SafeModeAssert(condition, message)
Definition: Macro.hpp:47
#define UserAssert(condition, message)
Definition: Macro.hpp:54
#define XmlAssert(condition, message)
Definition: XmlParser.hpp:52
std::map< const std::string, T * > Map
Definition: Mapped.hpp:58
static Map & get_map()
Definition: Mapped.hpp:87
static Variable & get(const std::string &id)
Definition: Mapped.hpp:121
Definition: SetOf.hpp:236
static SetOf< type > & get()
static EnergyBalance & get()
Definition: Singleton.hpp:127
Definition: XmlParser.hpp:122
static XmlParser & get()
void read_attribute(const Attribute::State, const std::string &, T &)
A class for managing contact with discrete elements (obsolete and not documented)
Definition: Standard.hpp:56
double get_adhesion_force() const
Definition: Standard.hpp:177
std::string _regularization_type
Definition: Standard.hpp:103
double get_dry_friction_slope() const
Definition: Standard.hpp:172
virtual void compute_reaction(DEM::DiscreteElement &de1, T &de2, const Geom::Vector &normal, const double &penetration)
Definition: Standard.hpp:310
double _dry_friction_slope
Definition: Standard.hpp:101
void set_dynamic_dry_friction_coeff(double)
Definition: Standard.hpp:135
void set_stiffness(double)
Definition: Standard.hpp:114
double _static_dry_friction_coeff
Definition: Standard.hpp:99
double get_dynamic_dry_friction_coeff() const
Definition: Standard.hpp:167
virtual void parse_xml()
Definition: Standard.hpp:210
virtual void info(std::ostream &) const
Definition: Standard.hpp:279
static std::string class_ID()
Definition: Standard.hpp:61
double get_stiffness() const
Definition: Standard.hpp:152
void set_restitution_coeff(double)
Definition: Standard.hpp:120
ContactLaw_Standard & operator=(const ContactLaw_Standard &)=delete
void set_dry_friction_slope(double)
Definition: Standard.hpp:142
double _dry_friction_coeff
Definition: Standard.hpp:102
void set_static_dry_friction_coeff(double)
Definition: Standard.hpp:128
double get_restitution_coeff() const
Definition: Standard.hpp:157
Math::Expression _normal_force
Definition: Standard.hpp:106
bool _normal_force_mode
Definition: Standard.hpp:107
double _dynamic_dry_friction_coeff
Definition: Standard.hpp:100
bool _exclude_bonded_element
Definition: Standard.hpp:95
double _stiffness
Definition: Standard.hpp:96
double _restitution_coeff
Definition: Standard.hpp:97
double _damping_factor
Definition: Standard.hpp:98
double _adhesion_force
Definition: Standard.hpp:105
double get_static_dry_friction_coeff() const
Definition: Standard.hpp:162
ContactLaw_Standard(const ContactLaw_Standard &)=delete
void set_adhesion_force(double)
Definition: Standard.hpp:147
virtual ~ContactLaw_Standard()
Definition: Standard.hpp:206
ContactLaw_Standard()
Definition: Standard.hpp:182
virtual double compute_critical_time_step() const
a pure virtual method able to return the critical time step value
Definition: Standard.hpp:294
double _dry_friction_life_time
Definition: Standard.hpp:104
A class for managing contact with discrete elements (obsolete and not documented)
Definition: ContactLaw.hpp:70
the discrete element is just a spherical Element with additional dedicated features
Definition: DiscreteElement.hpp:47
double get_radius() const
get the radius
Definition: DiscreteElement.hpp:85
a base class that represents an element
Definition: Element.hpp:55
bool is_bonded(const Element &el) const
ask if the current element is bonded to another one
Definition: Element.cpp:87
const Geom::Vector & get_position() const
get the current position vector of the element
Definition: ElementT.hpp:146
a pure virtual class that represents a perfect shape associated with a collection of discrete element
Definition: SupportShape.hpp:54
Definition: Surface.hpp:47
Definition: Vector.hpp:75
double norm() const
Vector unit() const
Definition: Expression.hpp:46
Definition: Variable.hpp:46
double get_mass() const
get the current mass value of the body
Definition: Body.cpp:58
Definition: EnergyBalance.hpp:50
void add_torque_on(const Body &, const std::string &label, const Geom::Vector &torque)
Definition: EnergyBalance.cpp:153
void add_force_on(const Node &, const std::string &label, const Geom::Vector &force)
Definition: EnergyBalance.cpp:143
bool is_enable() const
Definition: EnergyBalance.cpp:63
static granoo_endl endl
Definition: Out.hpp:106
Definition: Common.hpp:198
T max(const T v0, const T v1)
Definition: Exprtk.hpp:1463