73 UniInPlaneFriction(
unsigned uLabel,
const DofOwner *pDO,
75 virtual ~UniInPlaneFriction(
void);
76 virtual unsigned int iGetNumDof(
void)
const;
79 virtual std::ostream& DescribeDof(std::ostream& out,
const char *prefix,
bool bInitial)
const;
80 virtual std::ostream& DescribeEq(std::ostream& out,
const char *prefix,
bool bInitial)
const;
81 virtual unsigned int iGetNumPrivData(
void)
const;
82 virtual unsigned int iGetPrivDataIdx(
const char *s)
const;
83 virtual doublereal dGetPrivData(
unsigned int i)
const;
85 virtual void WorkSpaceDim(
integer* piNumRows,
integer* piNumCols)
const;
105 int iGetNumConnectedNodes(
void)
const;
106 void GetConnectedNodes(std::vector<const Node *>& connectedNodes)
const;
109 std::ostream& Restart(std::ostream& out)
const;
110 virtual unsigned int iGetInitialNumDof(
void)
const;
112 InitialWorkSpaceDim(
integer* piNumRows,
integer* piNumCols)
const;
120 static const int iNumDofGradient = 15;
124 inline explicit ContactPoint(
const Vec3& offset=
Zero3,
doublereal s=std::numeric_limits<doublereal>::max());
126 inline void AfterConvergence()
131 inline void UpdateReaction(
142 inline void UpdateReaction(
172 static const int iNumPrivDataGlobal = 1;
174 static const struct PrivateData
205 typedef std::vector<ContactPoint> ContactPointVec_t;
206 typedef ContactPointVec_t::iterator ContactPointIter_t;
207 typedef ContactPointVec_t::const_iterator const_ContactPointIter_t;
211 ContactPointVec_t ContactPoints1;
216 bool bEnableFriction;
223 UniInPlaneFriction::ContactPoint::ContactPoint(
const Vec3& offset,
doublereal s)
237 void UniInPlaneFriction::ContactPoint::UpdateReaction(
250 this->lambda = lambda;
264 const UniInPlaneFriction::PrivateData UniInPlaneFriction::rgPrivData[
iNumPrivData] =
290 UniInPlaneFriction::UniInPlaneFriction(
291 unsigned uLabel,
const DofOwner *pDO,
302 bEnableFriction(
false)
306 using namespace grad;
312 "Module: UniInPlaneFriction\n"
314 " This element implements the unilateral contact between a point and a plane\n"
316 " unilateral in plane,\n"
317 " node1, (label) <node1>,\n"
318 " [ offset, (integer) <count>,\n"
319 " (Vec3) <offset1>,\n"
320 " [stiffness, (real) <stiffness1>,]\n"
322 " epsilon, (real) <epsilon>,\n"
323 " node2, (label) <node2>,\n"
324 " [ offset, (Vec3) <offset>, ]\n"
325 " [ hinge, (Mat3x3) <hinge>, ]\n"
326 " [ initial assembly, (DriveCaller) <initial_assembly>, ]\n"
327 " [ offset plane, (DriveCaller) <normal_offset> ]"
342 silent_cerr(
"unilateral in plane(" << GetLabel() <<
"): keyword \"node1\" expected at line " << HP.
GetLineData() << std::endl);
349 silent_cerr(
"unilateral in plane(" << GetLabel() <<
"): structural node expected at line " << HP.
GetLineData() << std::endl);
359 silent_cerr(
"unilateral in plan(" << GetLabel()
360 <<
"): number of offsets must be greater than zero at line "
367 ContactPoints1.reserve(N);
369 for (
int i = 0; i < N; ++i)
373 ContactPoints1.push_back(ContactPoint(o1, s));
378 ContactPoints1.push_back(ContactPoint(
Zero3));
383 silent_cerr(
"unilateral in plane(" << GetLabel() <<
"): keyword \"epsilon\" expected at line " << HP.
GetLineData() << std::endl);
391 silent_cerr(
"unilateral in plane(" << GetLabel() <<
"): epsilon must be greater than zero at line " << HP.
GetLineData() << std::endl);
395 dFmax = HP.
IsKeyWord(
"max" "force" "increment") ? HP.
GetReal() : std::numeric_limits<doublereal>::max();
399 silent_cerr(
"unilateral in plane(" << GetLabel() <<
"): keyword \"node2\" expected at line " << HP.
GetLineData() << std::endl);
406 silent_cerr(
"unilateral in plane(" << GetLabel() <<
"): structural node expected at line " << HP.
GetLineData() << std::endl);
420 if (HP.
IsKeyWord(
"coulomb" "friction" "coefficient") || HP.
IsKeyWord(
"coulomb" "friction" "coefficient" "x"))
422 bEnableFriction =
true;
428 if (HP.
IsKeyWord(
"coulomb" "friction" "coefficient" "y")) {
436 if (HP.
IsKeyWord(
"static" "friction" "coefficient")
437 || HP.
IsKeyWord(
"static" "friction" "coefficient" "x")) {
440 if (HP.
IsKeyWord(
"static" "friction" "coefficient" "y")) {
450 if (HP.
IsKeyWord(
"sliding" "velocity" "coefficient")) {
456 if (HP.
IsKeyWord(
"sliding" "velocity" "exponent")) {
462 if (!(HP.
IsKeyWord(
"micro" "slip" "stiffness") || HP.
IsKeyWord(
"micro" "slip" "stiffness" "x"))) {
463 silent_cerr(
"unilateral in plane("
465 <<
"): keyword \"micro slip stiffness\" or \"micro slip stiffness x\" expected at line "
475 if (HP.
IsKeyWord(
"micro" "slip" "stiffness" "y")) {
483 if (HP.
IsKeyWord(
"micro" "slip" "damping") || HP.
IsKeyWord(
"micro" "slip" "damping" "x")) {
486 if (HP.
IsKeyWord(
"micro" "slip" "damping" "y")) {
496 if (HP.
IsKeyWord(
"viscous" "friction" "coefficient") || HP.
IsKeyWord(
"viscous" "friction" "coefficient" "x"))
501 if (HP.
IsKeyWord(
"viscous" "friction" "coefficient" "y"))
507 sigma2(2, 2) = sigma2(1, 1);
520 sigma0(1, 1) = sigma0x;
521 sigma0(2, 2) = sigma0y;
523 sigma1(1, 1) = sigma1x;
524 sigma1(2, 2) = sigma1y;
526 invMk2_sigma0 =
Inv(Mk2) * sigma0;
536 out <<
"unilateral in plane: " << GetLabel() <<
" " << pNode1->GetLabel() <<
" " << ContactPoints1.size() <<
" ";
538 for ( const_ContactPointIter_t it = ContactPoints1.begin(); it != ContactPoints1.end(); ++it )
539 out << it->o1 <<
" ";
541 out << pNode2->GetLabel() <<
" " << o2 <<
" " << Rp << std::endl;
544 UniInPlaneFriction::~UniInPlaneFriction(
void)
549 unsigned int UniInPlaneFriction::iGetNumDof(
void)
const
551 return ContactPoints1.size() * (1 + 2 * bEnableFriction);
556 const int iNumDof = 1 + 2 * bEnableFriction;
575 return GetDofType(i);
578 std::ostream& UniInPlaneFriction::DescribeDof(std::ostream& out,
const char *prefix,
bool bInitial)
const
580 integer iIndex = iGetFirstIndex();
582 const int N = ContactPoints1.size();
584 for (
int i = 1; i <= N; ++i )
586 out << prefix << ++iIndex <<
": reaction force [lambda(" << i <<
")]" << std::endl;
590 for (
int j = 1; j <= 2; ++j)
592 out << prefix << ++iIndex <<
": sticktion state [z" << j <<
"(" << i <<
")]" << std::endl;
600 std::ostream& UniInPlaneFriction::DescribeEq(std::ostream& out,
const char *prefix,
bool bInitial)
const
602 integer iIndex = iGetFirstIndex();
604 const int N = ContactPoints1.size();
606 for (
int i = 1; i <= N; ++i )
608 out << prefix << ++iIndex <<
": constraint equation [c" << i <<
"]" << std::endl;
612 for (
int j = 1; j <= 2; ++j)
614 out << prefix << ++iIndex <<
": sticktion state variation [Phi" << j <<
"(" << i <<
")]" << std::endl;
622 unsigned int UniInPlaneFriction::iGetNumPrivData(
void)
const
624 return iNumPrivDataGlobal + ContactPoints1.size() *
iNumPrivData;
627 unsigned int UniInPlaneFriction::iGetPrivDataIdx(
const char *s)
const
629 if (0 == strcmp(s,
"max" "dt"))
634 std::istringstream is(s);
639 std::getline(is, tok1,
'[');
646 i > ContactPoints1.size() )
653 if (tok1 == rgPrivData[j].name)
655 return iNumPrivDataGlobal + (i - 1) * iNumPrivData + j + 1;
660 silent_cerr(
"unilateral in plane(" << GetLabel() <<
"): private data \"" << s <<
"\" not available" << std::endl);
664 doublereal UniInPlaneFriction::dGetPrivData(
unsigned int i)
const
668 doublereal dtmax = std::numeric_limits<doublereal>::max();
670 for (const_ContactPointIter_t j = ContactPoints1.begin(); j != ContactPoints1.end(); ++j)
672 const doublereal dF = j->lambda - j->lambdaPrev;
674 if (std::abs(dF) > dFmax)
677 dtmax = std::min(dtmax, std::abs(dt / dF * dFmax));
684 const div_t idx = div(i - 1 - iNumPrivDataGlobal, iNumPrivData);
686 if ( idx.quot < 0 || ::
size_t(idx.quot) >= ContactPoints1.size() || idx.rem < 0 || idx.rem >=
iNumPrivData )
688 silent_cerr(
"unilateral in plane(" << GetLabel() <<
"): index " << i <<
" out of range" << std::endl);
692 const ContactPoint& cont = ContactPoints1[idx.quot];
696 case PrivateData::LAMBDA:
699 case PrivateData::DXN:
702 case PrivateData::TAU1:
703 case PrivateData::TAU2:
704 return cont.tau(idx.rem - PrivateData::TAU1 + 1);
706 case PrivateData::U1:
707 case PrivateData::U2:
708 return cont.U(idx.rem - PrivateData::U1 + 1);
710 case PrivateData::Z1:
711 case PrivateData::Z2:
712 return cont.z(idx.rem - PrivateData::Z1 + 1);
714 case PrivateData::ZP1:
715 case PrivateData::ZP2:
716 return cont.zP(idx.rem - PrivateData::ZP1 + 1);
718 case PrivateData::F1X:
719 case PrivateData::F1Y:
720 case PrivateData::F1Z:
721 return cont.F1(idx.rem - PrivateData::F1X + 1);
723 case PrivateData::M1X:
724 case PrivateData::M1Y:
725 case PrivateData::M1Z:
726 return cont.M1(idx.rem - PrivateData::M1X + 1);
728 case PrivateData::F2X:
729 case PrivateData::F2Y:
730 case PrivateData::F2Z:
731 return cont.F2(idx.rem - PrivateData::F2X + 1);
733 case PrivateData::M2X:
734 case PrivateData::M2Y:
735 case PrivateData::M2Z:
736 return cont.M2(idx.rem - PrivateData::M2X + 1);
752 os << std::setw(8) << GetLabel();
754 for (const_ContactPointIter_t it = ContactPoints1.begin(); it != ContactPoints1.end(); ++it)
755 os <<
" " << it->dXn <<
" " << it->F1 <<
" " << it->M1 <<
" " << it->F2 <<
" " << it->M2;
763 UniInPlaneFriction::WorkSpaceDim(
integer* piNumRows,
integer* piNumCols)
const
765 *piNumRows = -(ContactPoints1.size() * iNumDofGradient);
766 *piNumCols = iNumDofGradient;
775 using namespace grad;
787 using namespace grad;
796 template <
typename T>
804 using namespace grad;
809 const integer iFirstMomentumIndexNode1 = pNode1->iGetFirstMomentumIndex();
810 const integer iFirstMomentumIndexNode2 = pNode2->iGetFirstMomentumIndex();
811 const integer iFirstIndex = iGetFirstIndex();
812 integer iDofIndex = iFirstIndex;
814 const integer N = ContactPoints1.size();
815 const doublereal alpha = m_oInitialAssembly.dGet();
822 for (
integer i = 1; i <= N; ++i )
824 ContactPoint& cont = ContactPoints1[i - 1];
825 cont.dof.Reset(func);
827 pNode1->GetXCurr(X1, dCoef, func, &cont.dof);
828 pNode1->GetRCurr(R1, dCoef, func, &cont.dof);
829 pNode2->GetXCurr(X2, dCoef, func, &cont.dof);
830 pNode2->GetRCurr(R2, dCoef, func, &cont.dof);
832 XCurr.dGetCoef(++iDofIndex, lambda, 1., &cont.dof);
835 const Vec3 dX = X1 + R1 * o1 - X2 - R2 * o2;
836 const T dXn =
Dot(Rp.GetCol(3),
Transpose(R2) * dX) - m_oOffset.dGet() + lambda / cont.s;
838 const T d = 0.5 * (dXn - lambda);
839 const T
c = 0.5 * (dXn + lambda) -
sqrt(d * d + epsilon);
842 WorkVec.AddItem(iDofIndex, c * alpha / dCoef);
843 else WorkVec.AddItem(iDofIndex, lambda / dCoef);
845 Vec3 F1p = Rp.GetCol(3) * lambda;
849 Vec3 X1P, X2P, omega1, omega2;
851 pNode1->GetVCurr(X1P, dCoef, func, &cont.dof);
852 pNode1->GetWCurr(omega1, dCoef, func, &cont.dof);
853 pNode2->GetVCurr(X2P, dCoef, func, &cont.dof);
854 pNode2->GetWCurr(omega2, dCoef, func, &cont.dof);
858 const T norm_U =
sqrt(
Dot(U, U));
863 const Vec2 Mk_U = Mk * U;
864 const Vec2 Ms_U = Ms * U;
865 const Vec2 Mk2_U = Mk2 * U;
866 const Vec2 Ms2_U = Ms2 * U;
867 const T norm_Mk2_U =
sqrt(
Dot(Mk2_U, Mk2_U));
868 const T a0 = norm_Mk2_U /
sqrt(
Dot(Mk_U, Mk_U));
870 const T g = a0 + (a1 - a0) *
exp(-
pow(norm_U / vs,
a));
872 kappa = norm_Mk2_U / g;
875 for (
int i = 1; i <= 2; ++i)
877 XCurr.dGetCoef(iDofIndex + i, z(i), dCoef, &cont.dof);
878 XPrimeCurr.dGetCoef(iDofIndex + i, zP(i), 1., &cont.dof);
881 const Vec2 Phi = (U - invMk2_sigma0 * z * kappa - zP) * alpha;
883 for (
int i = 1; i <= 2; ++i)
889 WorkVec.AddItem(iDofIndex, Phi(i));
893 WorkVec.AddItem(iDofIndex, z(i));
897 tau = (sigma0 * z + sigma1 * zP) * lambda + sigma2 * U;
899 for (
int i = 1; i <= 2; ++i)
901 F1p -= Rp.GetCol(i) * tau(i);
904 cont.UpdateFriction(U, tau, z, zP);
908 const Vec3 F1 = R2 * F1p;
913 WorkVec.AddItem(iFirstMomentumIndexNode1 + 1, F1);
914 WorkVec.AddItem(iFirstMomentumIndexNode1 + 4, M1);
915 WorkVec.AddItem(iFirstMomentumIndexNode2 + 1, F2);
916 WorkVec.AddItem(iFirstMomentumIndexNode2 + 4, M2);
918 cont.UpdateReaction(F1, M1, F2, M2, dXn, lambda);
922 void UniInPlaneFriction::AfterConvergence(
const VectorHandler& X,
927 for (ContactPointIter_t i = ContactPoints1.begin(); i != ContactPoints1.end(); ++i)
929 i->AfterConvergence();
934 UniInPlaneFriction::iGetNumConnectedNodes(
void)
const
940 UniInPlaneFriction::GetConnectedNodes(std::vector<const Node *>& connectedNodes)
const
942 connectedNodes.resize(iGetNumConnectedNodes());
943 connectedNodes[0] = pNode1;
944 connectedNodes[1] = pNode2;
952 const int N = ContactPoints1.size();
954 integer iDofIndex = iGetFirstIndex();
956 for (
int i = 0; i < N; ++i )
958 X.
PutCoef(++iDofIndex, ContactPoints1[i].lambda);
962 for (
int j = 1; j <= 2; ++j)
964 X.
PutCoef(++iDofIndex, ContactPoints1[i].z(j));
965 XP.
PutCoef(iDofIndex, ContactPoints1[i].zP(j));
972 UniInPlaneFriction::Restart(std::ostream& out)
const
978 UniInPlaneFriction::iGetInitialNumDof(
void)
const
984 UniInPlaneFriction::InitialWorkSpaceDim(
993 UniInPlaneFriction::InitialAssJac(
1003 UniInPlaneFriction::InitialAssRes(
1018 if (!
SetUDE(
"unilateral" "in" "plane",rf))
1028 #ifndef STATIC_MODULES
1031 #error Dynamic linking is not supported on cygwin!
1032 #error Use STATIC_MODULES instead!
1040 if (!unilateral_in_plane_friction_set())
1042 silent_cerr(
"contact: "
1043 "module_init(" << module_name <<
") "
1044 "failed" << std::endl);
1056 #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)
int module_init(const char *module_name, void *pdm, void *php)
This function registers our user defined element for the math parser.
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)
bool uni_in_plane_set(void)
static const char * dof[]
virtual bool IsKeyWord(const char *sKeyWord)
std::ostream & Loadable(void) const
DotTraits< VectorExprLhs, VectorExprRhs, N_rows, N_rows >::ExpressionType Dot(const VectorExpression< VectorExprLhs, N_rows > &u, const VectorExpression< VectorExprRhs, N_rows > &v)
#define ASSERT(expression)
GradientExpression< UnaryExpr< FuncSqrt, Expr > > sqrt(const GradientExpression< Expr > &u)
virtual void PutCoef(integer iRow, const doublereal &dCoef)=0
VectorExpression< VectorCrossExpr< VectorLhsExpr, VectorRhsExpr >, 3 > Cross(const VectorExpression< VectorLhsExpr, 3 > &u, const VectorExpression< VectorRhsExpr, 3 > &v)
static std::stack< cleanup * > c
std::ostream & GetLogFile(void) const
bool SetUDE(const std::string &s, UserDefinedElemRead *rude)
DriveCaller * GetDriveCaller(bool bDeferred=false)
static const doublereal a
SparseSubMatrixHandler & SetSparse(void)
virtual HighParser::ErrOut GetLineData(void) const
Node * ReadNode(MBDynParser &HP, Node::Type type) const
bool UseText(int out) const
virtual doublereal GetReal(const doublereal &dDefval=0.0)