70 BallBearingContact(
unsigned uLabel,
const DofOwner *pDO,
72 virtual ~BallBearingContact(
void);
74 virtual void WorkSpaceDim(
integer* piNumRows,
integer* piNumCols)
const;
95 virtual unsigned int iGetNumPrivData(
void)
const;
96 virtual unsigned int iGetPrivDataIdx(
const char *s)
const;
97 virtual doublereal dGetPrivData(
unsigned int i)
const;
98 int iGetNumConnectedNodes(
void)
const;
99 void GetConnectedNodes(std::vector<const Node *>& connectedNodes)
const;
102 std::ostream& Restart(std::ostream& out)
const;
103 virtual unsigned int iGetNumDof(
void)
const;
104 virtual std::ostream& DescribeDof(std::ostream& out,
105 const char *prefix,
bool bInitial)
const;
106 virtual std::ostream& DescribeEq(std::ostream& out,
107 const char *prefix,
bool bInitial)
const;
110 virtual unsigned int iGetInitialNumDof(
void)
const;
112 InitialWorkSpaceDim(
integer* piNumRows,
integer* piNumCols)
const;
134 bool bEnableFriction;
164 std::vector<Washer> washers;
171 static const struct PrivData {
176 const struct BallBearingContact::PrivData
189 BallBearingContact::BallBearingContact(
190 unsigned uLabel,
const DofOwner *pDO,
199 dStictionStateEquScale(0.),
200 dStictionStateDofScale(0.),
201 tPrev(-std::numeric_limits<
doublereal>::max()),
202 tCurr(-std::numeric_limits<
doublereal>::max()),
203 dtMax(std::numeric_limits<
doublereal>::max()),
204 dFMax(std::numeric_limits<
doublereal>::max()),
206 bEnableFriction(
false),
213 "Module: ballbearing contact\n"
215 " ball bearing contact,\n"
216 " ball, (label) <node1>,\n"
217 " ball radius, (Scalar) <R>,\n"
218 " washers, (Integer) <N>,\n"
219 " (label) <node2>,\n"
220 " [offset, (Vec3) <o2>,]\n"
221 " [orientation, (OrientationMatrix) <Rt2>,\n"
223 " {elastic modulus, <E> |\n"
224 " elastic modulus ball, (Scalar) <E1>,\n"
225 " poisson ratio ball, (Scalar) <nu1>\n"
226 " elastic modulus washer, (Scalar) <E2>,\n"
227 " poisson ratio washer, (Scalar) <nu2>},\n"
228 " [damping factor, (Scalar) <ks>,]\n"
229 " {coulomb friction coefficient, (Scalar) <mu> |\n"
230 " coulomb friction coefficient x, (Scalar) <mux>,\n"
231 " coulomb friction coefficient y, (Scalar) <muy>},\n"
232 " [{static friction coefficient, (Scalar) <mus> |\n"
233 " static friction coefficient x, (Scalar) <musx>,\n"
234 " static friction coefficient y, (Scalar) <musy>},]\n"
235 " [sliding velocity coefficient, (Scalar) <vs>,]\n"
236 " [sliding velocity exponent, (Scalar) <gamma>,]\n"
237 " {micro slip stiffness, (Scalar) <sigma0> |\n"
238 " micro slip stiffness x, (Scalar) <sigma0x>,\n"
239 " micro slip stiffness y, (Scalar) <sigma0y>}\n"
240 " [,{micro slip damping, (Scalar) <sigma1>, |\n"
241 " micro slip damping x, (Scalar) <sigma1x>,\n"
242 " micro slip damping y, (Scalar) <sigma1y>}]\n"
254 silent_cerr(
"ball bearing contact" << GetLabel()
255 <<
"): keyword \"ball\" expected at line "
263 silent_cerr(
"ball bearing contact(" << GetLabel()
264 <<
"): keyword \"ball radius\" expected at line "
273 silent_cerr(
"ball bearing contact" << GetLabel()
274 <<
"): keyword \"washers\" expected at line "
283 for (std::vector<Washer>::iterator i = washers.begin(); i != washers.end(); ++i) {
301 if ( HP.
IsKeyWord(
"elastic" "modulus") ) {
304 if ( !HP.
IsKeyWord(
"elastic" "modulus" "ball") ) {
305 silent_cerr(
"ball bearing contact(" << GetLabel()
306 <<
"): keyword \"elastic modulus\" or "
307 "\"elastic modulus ball\" expected at line "
315 if ( !HP.
IsKeyWord(
"poisson" "ratio" "ball") ) {
316 silent_cerr(
"ball bearing contact(" << GetLabel()
317 <<
"): keyword \"poisson ratio ball\" expected at line "
325 if ( !HP.
IsKeyWord(
"elastic" "modulus" "washer") ) {
326 silent_cerr(
"ball bearing contact(" << GetLabel()
327 <<
"): keyword \"elastic modulus washer\" expected at line "
335 if ( !HP.
IsKeyWord(
"poisson" "ratio" "washer") ) {
336 silent_cerr(
"ball bearing contact(" << GetLabel()
337 <<
"): keyword \"poisson ratio washer\" expected at line "
345 E = 1 / ((1 - nu1 * nu1) / E1 + (1 - nu2 * nu2) / E2);
348 k = 4./3. * E *
sqrt(
R);
352 beta = 3./2. * ks * k;
357 if (HP.
IsKeyWord(
"coulomb" "friction" "coefficient")
358 || HP.
IsKeyWord(
"coulomb" "friction" "coefficient" "x")) {
359 bEnableFriction =
true;
365 if (HP.
IsKeyWord(
"coulomb" "friction" "coefficient" "y")) {
373 if (HP.
IsKeyWord(
"static" "friction" "coefficient")
374 || HP.
IsKeyWord(
"static" "friction" "coefficient" "x")) {
377 if (HP.
IsKeyWord(
"static" "friction" "coefficient" "y")) {
387 if (HP.
IsKeyWord(
"sliding" "velocity" "coefficient")) {
393 if (HP.
IsKeyWord(
"sliding" "velocity" "exponent")) {
399 if (!(HP.
IsKeyWord(
"micro" "slip" "stiffness") || HP.
IsKeyWord(
"micro" "slip" "stiffness" "x"))) {
400 silent_cerr(
"ball bearing contact("
402 <<
"): keyword \"micro slip stiffness\" or \"micro slip stiffness x\" expected at line "
412 if (HP.
IsKeyWord(
"micro" "slip" "stiffness" "y")) {
420 if (HP.
IsKeyWord(
"micro" "slip" "damping") || HP.
IsKeyWord(
"micro" "slip" "damping" "x")) {
423 if (HP.
IsKeyWord(
"micro" "slip" "damping" "y")) {
445 sigma0(1, 1) = sigma0x;
446 sigma0(2, 2) = sigma0y;
448 sigma1(1, 1) = sigma1x;
449 sigma1(2, 2) = sigma1y;
451 dStictionStateEquScale = HP.
IsKeyWord(
"stiction" "state" "equation" "scale") ? HP.
GetReal() : 1.;
452 dStictionStateDofScale = HP.
IsKeyWord(
"stiction" "state" "dof" "scale") ? HP.
GetReal() : 1.;
455 if (HP.
IsKeyWord(
"max" "force" "increment")) {
459 silent_cerr(
"ball bearing contact(" << GetLabel()
460 <<
"): max force increment must be greater than zero at line "
466 if (HP.
IsKeyWord(
"min" "force" "increment")) {
470 silent_cerr(
"ball bearing contact(" << GetLabel()
471 <<
"): min force increment must be greater than zero at line "
480 BallBearingContact::~BallBearingContact(
void)
492 BallBearingContact::WorkSpaceDim(
integer* piNumRows,
integer* piNumCols)
const
496 if (bEnableFriction) {
500 *piNumRows = iNumDof * washers.size();
501 *piNumCols = iNumDof * washers.size();
536 template <
typename T>
547 VVec3 X1, X1P, omega1;
549 VVec3 X2, X2P, omega2;
554 integer offset = std::numeric_limits<integer>::min();
555 const integer iFirstIndex = bEnableFriction ? iGetFirstIndex() : std::numeric_limits<
integer>::min();
556 const integer iFirstMomIndexNode1 = pNode1->iGetFirstMomentumIndex();
557 dtMax = std::numeric_limits<doublereal>::max();
559 for (std::vector<Washer>::iterator i = washers.begin(); i != washers.end(); ++i) {
561 pNode1->GetXCurr(X1, dCoef, func, &i->dof);
562 pNode1->GetVCurr(X1P, dCoef, func, &i->dof);
563 pNode1->GetWCurr(omega1, dCoef, func, &i->dof);
565 i->pNode2->GetXCurr(X2, dCoef, func, &i->dof);
566 i->pNode2->GetVCurr(X2P, dCoef, func, &i->dof);
567 i->pNode2->GetRCurr(R2, dCoef, func, &i->dof);
568 i->pNode2->GetWCurr(omega2, dCoef, func, &i->dof);
570 if (bEnableFriction) {
571 offset = 2 * (i - washers.begin());
573 for (
integer j = 1; j <= 2; ++j) {
574 XCurr.dGetCoef(iFirstIndex + j + offset, z(j), dCoef, &i->dof);
575 XPrimeCurr.dGetCoef(iFirstIndex + j + offset, zP(j), 1., &i->dof);
578 z *= dStictionStateDofScale;
579 zP *= dStictionStateDofScale;
581 for (
int j = 1; j <= 2; ++j) {
587 const VVec3 dX = X1 - X2;
595 const T dn_dt =
Dot(R2 * i->Rt2.GetCol(3), X1P - X2P -
Cross(omega2, dX));
599 norm_Fn = k *
pow(d, 3./2.) - beta *
sqrt(d) * dn_dt;
608 CheckTimeStep(*i, norm_Fn, d, dn_dt);
610 if (bEnableFriction) {
611 const VVec3 c1P = X1P -
Cross(omega1, R2 * VVec3(i->Rt2.GetCol(3) *
R));
612 const VVec3 c2P = X2P +
Cross(omega2, R2 * VVec3(i->o2 + i->Rt2 * v));
616 const VVec3 Deltac = X1 - X2 - R2 * VVec3(i->o2 + i->Rt2 * l);
618 const VVec2 uP =
Transpose(SubMatrix<1, 3, 1, 2>(i->Rt2)) * VVec3(
Transpose(R2) * VVec3(c1P - c2P -
Cross(omega2, Deltac)));
620 for (
int j = 1; j <= 2; ++j) {
624 tau = (sigma0 * z + sigma1 * zP) * norm_Fn;
625 const T Norm_uP =
Norm(uP);
630 const T a0 =
Norm(Mk2 * uP);
631 const T a1 = a0 /
Norm(Mk * uP);
632 const T g = a1 + (
Norm(Ms2 * uP) /
Norm(Ms * uP) - a1) *
exp(-
pow(Norm_uP / vs, gamma));
637 Phi = (uP - inv_Mk2 * VVec2(sigma0 * VVec2(z * kappa)) - zP) * dStictionStateEquScale;
640 const VVec3 R2_Rt2_e3_n = R2 * VVec3(i->Rt2.GetCol(3) * n);
642 const VVec3 F1 = R2 * VVec3(i->Rt2 * VVec3(-tau(1), -tau(2), norm_Fn));
643 const VVec3 M1 = -
Cross(R2_Rt2_e3_n, F1);
644 const VVec3 F2 = -F1;
645 const VVec3 M2 =
Cross(VVec3(dX - R2_Rt2_e3_n), F2);
647 const integer iFirstMomIndexNode2 = i->pNode2->iGetFirstMomentumIndex();
649 WorkVec.AddItem(iFirstMomIndexNode1 + 1, F1);
650 WorkVec.AddItem(iFirstMomIndexNode1 + 4, M1);
651 WorkVec.AddItem(iFirstMomIndexNode2 + 1, F2);
652 WorkVec.AddItem(iFirstMomIndexNode2 + 4, M2);
654 if (bEnableFriction) {
655 for (
int j = 1; j <= 2; ++j) {
656 WorkVec.AddItem(iFirstIndex + j + offset, Phi(j));
666 w.dd_dtCurr = -dn_dt;
674 if (w.FnPrev < dFMin && w.FnCurr < dFMin) {
683 if ((w.dCurr > 0 && w.dPrev < 0) || (w.dCurr < 0 && w.dPrev > 0)) {
685 }
else if (w.dCurr >= 0. && w.dPrev >= 0.) {
699 const doublereal dd_dt2 = (w.dd_dtCurr - w.dd_dtPrev) / (tCurr - tPrev);
700 const doublereal p = 2 * w.dd_dtPrev / dd_dt2;
710 for (
int i = 0; i < 2; ++i) {
711 if (dt[i] > 0. && dt[i] < dtMax) {
723 void BallBearingContact::AfterConvergence(
const VectorHandler& X,
728 for (std::vector<Washer>::iterator i = washers.begin(); i != washers.end(); ++i) {
730 i->dd_dtPrev = i->dd_dtCurr;
731 i->FnPrev = i->FnCurr;
736 BallBearingContact::iGetNumPrivData(
void)
const
741 unsigned int BallBearingContact::iGetPrivDataIdx(
const char *s)
const
743 if (0 == strcmp(s,
"max" "dt")) {
749 if (1 != sscanf(s, rgPrivData[i].szPattern, &iWasher)) {
753 if (iWasher <= 0 || iWasher > washers.size()) {
757 return (iWasher - 1) * iNumPrivData + i + 2u;
764 doublereal BallBearingContact::dGetPrivData(
unsigned int i)
const
770 const div_t d = div(i - 2u, iNumPrivData);
772 if (d.quot < 0 ||
size_t(d.quot) >= washers.size()) {
773 silent_cerr(
"ballbearingcontact(" << GetLabel()
774 <<
"): invalid index " << i << std::endl);
778 const Washer& w = washers[d.quot];
792 return w.z(d.rem - 2);
796 return w.zP(d.rem - 4);
800 return w.uP(d.rem - 6);
803 silent_cerr(
"ballbearingcontact(" << GetLabel()
804 <<
"): invalid index " << i << std::endl);
810 BallBearingContact::iGetNumConnectedNodes(
void)
const
812 return washers.size() + 1;
816 BallBearingContact::GetConnectedNodes(std::vector<const Node *>& connectedNodes)
const
818 connectedNodes.reserve(iGetNumConnectedNodes());
819 connectedNodes.clear();
820 connectedNodes.push_back(pNode1);
822 for (std::vector<Washer>::const_iterator i = washers.begin(); i != washers.end(); ++i) {
823 connectedNodes.push_back(i->pNode2);
836 BallBearingContact::Restart(std::ostream& out)
const
841 unsigned int BallBearingContact::iGetNumDof(
void)
const
843 return bEnableFriction ? 2 * washers.size() : 0;
846 std::ostream& BallBearingContact::DescribeDof(std::ostream& out,
847 const char *prefix,
bool bInitial)
const
849 if (bEnableFriction) {
850 const integer iIndex = iGetFirstIndex();
852 for (
size_t i = 0; i < washers.size(); ++i) {
853 for (
int j = 1; j <= 2; ++j) {
854 out << prefix << iIndex + j + 2 * i <<
": stiction state z" << j <<
"[" << i <<
"]" << std::endl;
862 std::ostream& BallBearingContact::DescribeEq(std::ostream& out,
863 const char *prefix,
bool bInitial)
const
865 if (bEnableFriction) {
866 const integer iIndex = iGetFirstIndex();
868 for (
size_t i = 0; i < washers.size(); ++i) {
869 for (
int j = 1; j <= 2; ++j) {
870 out << prefix << iIndex + j + 2 * i <<
": ode for stiction state z" << j <<
"[" << i <<
"]" << std::endl;
889 BallBearingContact::iGetInitialNumDof(
void)
const
895 BallBearingContact::InitialWorkSpaceDim(
904 BallBearingContact::InitialAssJac(
914 BallBearingContact::InitialAssRes(
929 if (!
SetUDE(
"ball" "bearing" "contact", rf))
941 #ifndef STATIC_MODULES
950 silent_cerr(
"ballbearing_contact: "
951 "module_init(" << module_name <<
") "
952 "failed" << std::endl);
962 #endif // ! STATIC_MODULE
flag fReadOutput(MBDynParser &HP, const T &t) const
GradientExpression< UnaryExpr< FuncExp, Expr > > exp(const GradientExpression< Expr > &u)
Mat3x3 GetRotRel(const ReferenceFrame &rf)
scalar_func_type dGetValue(scalar_func_type d)
const Vec3 Zero3(0., 0., 0.)
MatrixExpression< TransposedMatrix< MatrixDirectExpr< Matrix< T, N_rows, N_cols > > >, N_cols, N_rows > Transpose(const Matrix< T, N_rows, N_cols > &A)
GradientExpression< BinaryExpr< FuncPow, LhsExpr, RhsExpr > > pow(const GradientExpression< LhsExpr > &u, const GradientExpression< RhsExpr > &v)
#define MBDYN_EXCEPT_ARGS
virtual void ResizeReset(integer)
virtual integer GetInt(integer iDefval=0)
doublereal dGetTime(void) const
const Mat3x3 Eye3(1., 0., 0., 0., 1., 0., 0., 0., 1.)
static const unsigned int iNumPrivData
std::vector< Hint * > Hints
void func(const T &u, const T &v, const T &w, doublereal e, T &f)
Vec3 GetPosRel(const ReferenceFrame &rf)
Matrix< T, 2, 2 > Inv(const Matrix< T, 2, 2 > &A)
static const char * dof[]
virtual bool IsKeyWord(const char *sKeyWord)
doublereal copysign(doublereal x, doublereal y)
DotTraits< VectorExprLhs, VectorExprRhs, N_rows, N_rows >::ExpressionType Dot(const VectorExpression< VectorExprLhs, N_rows > &u, const VectorExpression< VectorExprRhs, N_rows > &v)
GradientExpression< UnaryExpr< FuncSqrt, Expr > > sqrt(const GradientExpression< Expr > &u)
VectorExpression< VectorCrossExpr< VectorLhsExpr, VectorRhsExpr >, 3 > Cross(const VectorExpression< VectorLhsExpr, 3 > &u, const VectorExpression< VectorRhsExpr, 3 > &v)
VectorExpression< VectorExpr, N_rows >::ScalarType Norm(const VectorExpression< VectorExpr, N_rows > &u)
bool SetUDE(const std::string &s, UserDefinedElemRead *rude)
static const doublereal a
SparseSubMatrixHandler & SetSparse(void)
virtual HighParser::ErrOut GetLineData(void) const
Node * ReadNode(MBDynParser &HP, Node::Type type) const
virtual doublereal GetReal(const doublereal &dDefval=0.0)