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)