30 #ifndef _libDEM_ContactLaw_Standard_hpp_
31 #define _libDEM_ContactLaw_Standard_hpp_
41 #include "GranOO3/DEM/Util/Formula.hpp"
61 static std::string
class_ID() {
return "Standard";}
72 virtual void info(std::ostream &)
const;
113 template <
class T>
void
115 UserAssert(val >= 0.,
"The stiffness must be positive");
119 template <
class T>
void
122 "The RestitutionCoeff must be between [0,1]");
123 _restitution_coeff = val;
124 _damping_factor = DEM::restitution_coeff_to_damping_factor(_restitution_coeff);
127 template <
class T>
void
130 "The StaticDryFrictionCoeff must be between [0,1]");
131 _static_dry_friction_coeff = val;
134 template <
class T>
void
137 "The DynamicDryFrictionCoeff must be between [0,1]");
138 _dynamic_dry_friction_coeff = val;
141 template <
class T>
void
143 _dry_friction_slope = val;
146 template <
class T>
void
148 _adhesion_force = val;
151 template <
class T>
double
156 template <
class T>
double
158 return _restitution_coeff;
161 template <
class T>
double
163 return _dynamic_dry_friction_coeff;
166 template <
class T>
double
168 return _dynamic_dry_friction_coeff;
171 template <
class T>
double
173 return _dry_friction_slope;
176 template <
class T>
double
178 return _adhesion_force;
184 _exclude_bonded_element(false),
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.),
196 _normal_force_mode(false) {
199 if (m.count(
"d") ==
false) {
209 template <
class T>
void
212 parser.
read_attribute(Attr::GRANOO_OPTIONAL,
"Stiffness", _stiffness);
214 std::string FnExpr =
"";
215 parser.
read_attribute(Attr::GRANOO_OPTIONAL,
"NormalForce", FnExpr);
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);
229 XmlAssert((_stiffness==0. && FnExpr!=
"") || (_stiffness>0. && FnExpr==
""),
230 "You cannot use both Stiffness and NormalForce !");
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 !");
237 if (FnExpr.find(
"d") == std::string::npos)
240 _normal_force.set(FnExpr);
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]");
251 if (_restitution_coeff >= 0.) {
253 _damping_factor = DEM::restitution_coeff_to_damping_factor(_restitution_coeff);
254 }
else if (_damping_factor >= 0.) {
256 _restitution_coeff = DEM::damping_factor_To_restitution_coeff(_damping_factor);
260 XmlAssert(_regularization_type ==
"" || _regularization_type ==
"piecewise" || _regularization_type ==
"exponential",
261 "Available RegularizationTypes are 'piecewise' and 'exponential'");
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.");
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");
278 template <
class T>
void
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;
293 template <
class T>
double
299 for (
unsigned int i = 0; i<set.
size(); i++) {
300 minMass = set(i).get_mass() < minMass ? set(i).get_mass() : minMass;
302 return sqrt(minMass/get_stiffness());
309 template <
class T>
void
313 const double& penetration) {
315 if (_exclude_bonded_element) {
322 SafeModeAssert(penetration >= 0,
"The penetration between de1 and de2 must be positve");
326 if (_normal_force_mode) {
328 Fn = normal*_normal_force.value();
330 Fn = normal*_stiffness*penetration;
332 APPLY_FORCE(Fn, -Fn,
"[ContactLaw_Standard]_Elas");
335 if (_static_dry_friction_coeff > 0. || _dynamic_dry_friction_coeff > 0. || _dry_friction_coeff > 0) {
345 Vrel -= normal*(Vrel*normal);
349 const double VrelModulus = Vrel.
norm();
351 if (_regularization_type ==
"piecewise") {
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;
360 }
else if (_regularization_type ==
"exponential") {
362 mu = _dynamic_dry_friction_coeff + (_static_dry_friction_coeff-_dynamic_dry_friction_coeff)*exp(-VrelModulus/_dry_friction_life_time);
365 mu = (_dry_friction_slope*VrelModulus < _dry_friction_coeff ) ? _dry_friction_slope*VrelModulus : _dry_friction_coeff;
369 APPLY_FORCE(-Ft, Ft,
"[ContactLaw_Standard]_Fric");
370 APPLY_TORQUE(-(-AO1)^Ft, (-AO2)^Ft,
"[ContactLaw_Standard]_Fric");
374 if (_adhesion_force > 0.) {
376 APPLY_FORCE(Fa, -Fa,
"[Contactlaw_Standard]_Adhe");
380 if (_restitution_coeff != 0.) {
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;
389 APPLY_FORCE(Fd, -Fd,
"[ContactLaw_Standard]_Damp");
393 template<>
inline void
397 const double& penetration) {
398 SafeModeAssert(penetration >= 0,
"The penetration between de1 and de2 must be positve");
403 if (_normal_force_mode) {
405 Fn = normal*_normal_force.value();
407 Fn = normal*_stiffness*penetration;
411 energyBalance.
add_force_on(de,
"[ContactLaw_Standard]_Elas", Fn);
414 if (_static_dry_friction_coeff > 0. || _dynamic_dry_friction_coeff > 0. || _dry_friction_coeff > 0) {
424 Vrel -= normal*(Vrel*normal);
427 const double VrelModulus = Vrel.
norm();
429 if (_regularization_type ==
"piecewise") {
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;
439 }
else if (_regularization_type ==
"exponential") {
441 mu = _dynamic_dry_friction_coeff + (_static_dry_friction_coeff-_dynamic_dry_friction_coeff)*exp(-VrelModulus*1e8);
444 mu = (_dry_friction_slope*VrelModulus < _dry_friction_coeff ) ? _dry_friction_slope*VrelModulus : _dry_friction_coeff;
450 de.torque() -= (-AO1)^Ft;
453 energyBalance.
add_force_on (de,
"[ContactLaw_Standard]_Fric", -Ft);
454 energyBalance.
add_torque_on(de,
"[ContactLaw_Standard]_Fric", AO1^Ft);
459 if (_adhesion_force > 0.) {
464 energyBalance.
add_force_on(de,
"[ContactLaw_Standard]_Adhe", Fa);
468 if (_restitution_coeff != 0.) {
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;
477 energyBalance.
add_force_on(de,
"[ContactLaw_Standard]_Damp", Fd);
#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
void read_attribute(const Attribute::State, const std::string &, T &)
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
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