MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
module-inline_friction.cc
Go to the documentation of this file.
1 /*
2  * MBDyn (C) is a multibody analysis code.
3  * http://www.mbdyn.org
4  *
5  * Copyright (C) 1996-2017
6  *
7  * Pierangelo Masarati <masarati@aero.polimi.it>
8  * Paolo Mantegazza <mantegazza@aero.polimi.it>
9  *
10  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
11  * via La Masa, 34 - 20156 Milano, Italy
12  * http://www.aero.polimi.it
13  *
14  * Changing this copyright notice is forbidden.
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 (version 2 of the License).
19  *
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, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29  */
30 
31 /*
32  AUTHOR: Reinhard Resch <r.resch@secop.com>
33  Copyright (C) 2011(-2017) all rights reserved.
34 
35  The copyright of this code is transferred
36  to Pierangelo Masarati and Paolo Mantegazza
37  for use in the software MBDyn as described
38  in the GNU Public License version 2.1
39 */
40 
41 #include <algorithm>
42 #include <cassert>
43 #include <cfloat>
44 #include <cmath>
45 #include <cstdlib>
46 #include <cstring>
47 #include <iostream>
48 #include <iomanip>
49 #include <sstream>
50 #include <limits>
51 #include <vector>
52 
53 #ifdef HAVE_CONFIG_H
54 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
55 #endif /* HAVE_CONFIG_H */
56 
57 #include <dataman.h>
58 #include <userelem.h>
59 
60 #include "module-inline_friction.h"
61 
62 class InlineFriction: virtual public Elem, public UserDefinedElem
63 {
64 public:
65  InlineFriction(unsigned uLabel, const DofOwner *pDO,
66  DataManager* pDM, MBDynParser& HP);
67  virtual ~InlineFriction(void);
68  virtual unsigned int iGetNumDof(void) const;
69  virtual DofOrder::Order GetDofType(unsigned int i) const;
70  virtual DofOrder::Order GetEqType(unsigned int i) const;
71  virtual std::ostream& DescribeDof(std::ostream& out, const char *prefix, bool bInitial) const;
72  virtual std::ostream& DescribeEq(std::ostream& out, const char *prefix, bool bInitial) const;
73  virtual unsigned int iGetNumPrivData(void) const;
74  virtual unsigned int iGetPrivDataIdx(const char *s) const;
75  virtual doublereal dGetPrivData(unsigned int i) const;
76  virtual void Output(OutputHandler& OH) const;
77  virtual void WorkSpaceDim(integer* piNumRows, integer* piNumCols) const;
80  doublereal dCoef,
81  const VectorHandler& XCurr,
82  const VectorHandler& XPrimeCurr);
84  AssRes(SubVectorHandler& WorkVec,
85  doublereal dCoef,
86  const VectorHandler& XCurr,
87  const VectorHandler& XPrimeCurr);
88  int iGetNumConnectedNodes(void) const;
89  void GetConnectedNodes(std::vector<const Node *>& connectedNodes) const;
92  std::ostream& Restart(std::ostream& out) const;
93  virtual unsigned int iGetInitialNumDof(void) const;
94  virtual void
95  InitialWorkSpaceDim(integer* piNumRows, integer* piNumCols) const;
98  const VectorHandler& XCurr);
100  InitialAssRes(SubVectorHandler& WorkVec, const VectorHandler& XCurr);
101 
102  private:
103  inline doublereal SlidingVelocity(const Vec3& X1, const Mat3x3& R1, const Vec3& XP1, const Vec3& omega1, const Vec3& X2, const Mat3x3& R2, const Vec3& XP2, const Vec3& omega2) const;
104  inline doublereal NormalForceMagnitude() const;
105  inline doublereal FrictionCoefficient(doublereal DeltaXP) const;
106  inline doublereal FrictionForce(doublereal DeltaXP) const;
107 
108  private:
114 
116  {
117  L1 = 0,
118  L2 = 1
119  };
120 
124 
132 };
133 
135  unsigned uLabel, const DofOwner *pDO,
136  DataManager* pDM, MBDynParser& HP)
137 : Elem(uLabel, flag(0)),
138  UserDefinedElem(uLabel, pDO),
139  pNode1(0),
140  o1(Zero3),
141  e(Eye3),
142  pNode2(0),
143  o2(Zero3),
144  z(0.),
145  zP(0.),
146  mus(0.),
147  muc(0.),
148  vs(1.),
149  iv(1.),
150  kv(0.),
151  delta(1.),
152  PhiScale(1.)
153 {
154  for (int i = 0; i < 2; ++i) {
155  lambda[i] = 0;
156  }
157 
158  // help
159  if (HP.IsKeyWord("help")) {
160  silent_cout(
161  "\n"
162  "Module: InlineFriction\n"
163  "\n"
164  " This element implements a inline joint with friction\n"
165  "\n"
166  " inline friction,\n"
167  " node1, (label) <node1>,\n"
168  " [ offset, (Vec3) <offset>, ]\n"
169  " [ hinge, (Mat3x3) <orientation>, ]\n"
170  " node2, (label) <node2>,\n"
171  " [ offset, (Vec3) <offset>, ]\n"
172  " coulomb friction coefficient, (real) <muc>,\n"
173  " static friction coefficient, (real) <mus>,\n"
174  " sliding velocity coefficient, (real) <vs>,\n"
175  " [ sliding velocity exponent, (real) <i>, ]\n"
176  " micro slip displacement, (real) <delta>,\n"
177  " [ initial stiction state, (real) <z0>, ]\n"
178  " [ initial stiction derivative, (real) <zP0>, ]\n"
179  " [ viscous friction coefficient, (real) <kv>, ]\n"
180  " [ stiction state equation scale, (real) <PhiScale> ]\n"
181  "\n"
182  << std::endl);
183 
184  if (!HP.IsArg()) {
185  /*
186  * Exit quietly if nothing else is provided
187  */
188  throw NoErr(MBDYN_EXCEPT_ARGS);
189  }
190  }
191 
192  if ( !HP.IsKeyWord("node1") ) {
193  silent_cerr("inline friction(" << GetLabel() << "): keyword \"node1\" expected at line " << HP.GetLineData() << std::endl);
195  }
196 
197  pNode1 = dynamic_cast<StructNode*>(pDM->ReadNode(HP,Node::STRUCTURAL));
198 
199  if (!pNode1) {
200  silent_cerr("inline friction(" << GetLabel() << "): structural node expected at line " << HP.GetLineData() << std::endl);
202  }
203 
204  const ReferenceFrame refNode1(pNode1);
205 
206  if (HP.IsKeyWord("offset")) {
207  o1 = HP.GetPosRel(refNode1);
208  }
209 
210  if (HP.IsKeyWord("hinge") || HP.IsKeyWord("orientation")) {
211  e = HP.GetRotRel(refNode1);
212  }
213 
214  if (!HP.IsKeyWord("node2")) {
215  silent_cerr("inline friction(" << GetLabel() << "): keyword \"node2\" expected at line " << HP.GetLineData() << std::endl);
217  }
218 
219  pNode2 = dynamic_cast<StructNode*>(pDM->ReadNode(HP,Node::STRUCTURAL));
220 
221  if (!pNode2) {
222  silent_cerr("inline friction(" << GetLabel() << "): structural node expected at line " << HP.GetLineData() << std::endl);
224  }
225 
226  if (HP.IsKeyWord("offset")) {
227  const ReferenceFrame refNode2(pNode2);
228 
229  o2 = HP.GetPosRel(refNode2);
230  }
231 
232  if (HP.IsKeyWord("coulomb" "friction" "coefficient")) {
233  muc = HP.GetReal();
234 
235  if (muc < 0) {
236  silent_cerr("inline friction(" << GetLabel() << "): coulomb friction coefficient must be greater than zero at line " << HP.GetLineData() << std::endl);
238  }
239 
240  if (HP.IsKeyWord("static" "friction" "coefficient")) {
241  mus = HP.GetReal();
242  } else {
243  mus = muc;
244  }
245 
246  if (mus < 0) {
247  silent_cerr("inline friction(" << GetLabel() << "): static friction coefficient must be greater than or equal to zero at line " << HP.GetLineData() << std::endl);
249  }
250 
251  if (HP.IsKeyWord("sliding" "velocity" "coefficient")) {
252  vs = HP.GetReal();
253  }
254 
255  if (vs <= 0.) {
256  silent_cerr("inline friction(" << GetLabel() << "): sliding velocity coefficient must be greater than zero at line " << HP.GetLineData() << std::endl);
258  }
259 
260  if (HP.IsKeyWord("sliding" "velocity" "exponent")) {
261  iv = HP.GetReal();
262  }
263 
264  if (!HP.IsKeyWord("micro" "slip" "displacement")) {
265  silent_cerr("inline friction(" << GetLabel() << "): keyword \"micro slip displacement\" expected at line " << HP.GetLineData() << std::endl);
267  }
268 
269  delta = HP.GetReal();
270 
271  if (delta <= 0) {
272  silent_cerr("inline friction(" << GetLabel() << "): micro slip displacement must be greater than zero at line " << HP.GetLineData() << std::endl);
274  }
275 
276  if (HP.IsKeyWord("initial" "stiction" "state")) {
277  z = HP.GetReal();
278  }
279 
280  if (std::abs(z) > 1.) {
281  silent_cerr("inline friction(" << GetLabel() << "): initial stiction state must be between -1 and 1 at line " << HP.GetLineData() << std::endl);
283  }
284 
285  if (HP.IsKeyWord("initial" "stiction" "derivative")) {
286  zP = HP.GetReal();
287  }
288 
289  z *= delta;
290  zP *= delta;
291  }
292 
293  if (HP.IsKeyWord("viscous" "friction" "coefficient")) {
294  kv = HP.GetReal();
295  }
296 
297  if (kv < 0) {
298  silent_cerr("inline friction(" << GetLabel() << "): viscous friction coefficient must be greater than or equal to zero at line " << HP.GetLineData() << std::endl);
300  }
301 
302  if (HP.IsKeyWord("stiction" "state" "equation" "scale")) {
303  PhiScale = HP.GetReal();
304  }
305 
306  if (PhiScale == 0.) {
307  silent_cerr("inline friction(" << GetLabel() << "): stiction state equation scale must not be equal to zero at line " << HP.GetLineData() << std::endl);
309  }
310 
312 
313  std::ostream& out = pDM->GetLogFile();
314 
315  out << "inline friction: " << GetLabel() << " "
316  << pNode1->GetLabel() << " "
317  << o1 << " "
318  << e << " "
319  << pNode2->GetLabel() << " " << o2 << " "
320  << muc << " "
321  << mus << " "
322  << vs << " "
323  << iv << " "
324  << kv << " "
325  << delta << " "
326  << z << " "
327  << zP
328  << std::endl;
329 }
330 
332 {
333  // destroy private data
334 }
335 
336 unsigned int InlineFriction::iGetNumDof(void) const
337 {
338  return 2u + 1u * (muc > 0.);
339 }
340 
342 {
343  switch (i) {
344  case 0:
345  case 1:
346  return DofOrder::ALGEBRAIC;
347  case 2:
348  return DofOrder::DIFFERENTIAL;
349  default:
350  ASSERT(0);
352  }
353 }
354 
356 {
357  switch (i) {
358  case 0:
359  case 1:
360  return DofOrder::ALGEBRAIC;
361  case 2:
362  return DofOrder::DIFFERENTIAL;
363  default:
364  ASSERT(0);
366  }
367 }
368 
369 std::ostream& InlineFriction::DescribeDof(std::ostream& out, const char *prefix, bool bInitial) const
370 {
371  const integer iFirstIndex = iGetFirstIndex();
372 
373  out << prefix << iFirstIndex + 1 << "->" << iFirstIndex + 2 << ": reaction forces [lambda1, lambda2]" << std::endl;
374 
375  if (bInitial) {
376  out << prefix << iFirstIndex + 3 << "->" << iFirstIndex + 4 << ": reaction force derivatives [lambdaP1, lambdaP2]" << std::endl;
377  } else if (muc > 0) {
378  out << prefix << iFirstIndex + 3 << ": stiction state [z]" << std::endl;
379  }
380 
381  return out;
382 }
383 
384 std::ostream& InlineFriction::DescribeEq(std::ostream& out, const char *prefix, bool bInitial) const
385 {
386  const integer iFirstIndex = iGetFirstIndex();
387 
388  out << prefix << iFirstIndex + 1 << "->" << iFirstIndex + 2 << ": position constraints [c1, c2]" << std::endl;
389 
390  if (bInitial) {
391  out << prefix << iFirstIndex + 3 << "->" << iFirstIndex + 4 << ": velocity constraints [cP1, cP2]" << std::endl;
392  } else if (muc > 0) {
393  out << prefix << iFirstIndex + 3 << ": stick slip transition [Phi]" << std::endl;
394  }
395 
396  return out;
397 }
398 
399 unsigned int InlineFriction::iGetNumPrivData(void) const
400 {
401  return 8u;
402 }
403 
404 unsigned int InlineFriction::iGetPrivDataIdx(const char *s) const
405 {
406  static const struct {
407  int index;
408  char name[8];
409  } data[] = {
410  { 1, "lambda1" },
411  { 2, "lambda2" },
412  { 3, "tau" },
413  { 4, "mu" },
414  { 5, "z" },
415  { 6, "zP" },
416  { 7, "v" },
417  { 8, "Pf" }
418  };
419 
420  const int N = iGetNumPrivData();
421 
422  for (int i = 0; i < N; ++i) {
423  if (0 == strcmp(data[i].name, s)) {
424  return data[i].index;
425  }
426  }
427 
428  return 0;
429 }
430 
432 {
433  const Vec3& X1 = pNode1->GetXCurr();
434  const Mat3x3& R1 = pNode1->GetRCurr();
435  const Vec3& XP1 = pNode1->GetVCurr();
436  const Vec3& omega1 = pNode1->GetWCurr();
437  const Vec3& X2 = pNode2->GetXCurr();
438  const Mat3x3& R2 = pNode2->GetRCurr();
439  const Vec3& XP2 = pNode2->GetVCurr();
440  const Vec3& omega2 = pNode2->GetWCurr();
441 
442  switch (i) {
443  case 1:
444  case 2:
445  return lambda[i - 1];
446  case 3:
447  return FrictionForce(SlidingVelocity(X1, R1, XP1, omega1, X2, R2, XP2, omega2));
448  case 4:
449  return FrictionCoefficient(SlidingVelocity(X1, R1, XP1, omega1, X2, R2, XP2, omega2));
450  case 5:
451  return z;
452  case 6:
453  return zP;
454  case 7:
455  return SlidingVelocity(X1, R1, XP1, omega1, X2, R2, XP2, omega2);
456  case 8:
457  {
458  const double v = SlidingVelocity(X1, R1, XP1, omega1, X2, R2, XP2, omega2);
459  return -v * FrictionForce(v);
460  }
461  default:
462  silent_cerr("inline friction(" << GetLabel() << "): invalid private data index " << i << std::endl);
464  }
465 }
466 
467 void
469 {
470  if ( bToBeOutput() )
471  {
473  {
474  std::ostream& os = OH.Loadable();
475 
476  os << std::setw(8) << GetLabel() << " " << lambda[L1] << " " << lambda[L2] << " " << z << " " << zP << std::endl;
477  }
478  }
479 }
480 
481 void
482 InlineFriction::WorkSpaceDim(integer* piNumRows, integer* piNumCols) const
483 {
484  *piNumRows = *piNumCols = 14 + 1 * (muc > 0);
485 }
486 
489  doublereal dCoef,
490  const VectorHandler& XCurr,
491  const VectorHandler& XPrimeCurr)
492 {
493  integer iNumRows, iNumCols;
494  WorkSpaceDim(&iNumRows, &iNumCols);
495 
496  FullSubMatrixHandler& WorkMat = WorkMatVar.SetFull();
497 
498  WorkMat.ResizeReset(iNumRows, iNumCols);
499 
500  const integer iFirstMomentumIndexNode1 = pNode1->iGetFirstMomentumIndex();
501  const integer iFirstPositionIndexNode1 = pNode1->iGetFirstPositionIndex();
502  const integer iFirstMomentumIndexNode2 = pNode2->iGetFirstMomentumIndex();
503  const integer iFirstPositionIndexNode2 = pNode2->iGetFirstPositionIndex();
504  const integer iFirstIndex = iGetFirstIndex();
505  const integer iNumDof = iGetNumDof();
506 
507  for (integer i = 1; i <= 6; ++i) {
508  WorkMat.PutRowIndex(i, iFirstMomentumIndexNode1 + i);
509  WorkMat.PutColIndex(i, iFirstPositionIndexNode1 + i);
510  WorkMat.PutRowIndex(i + 6, iFirstMomentumIndexNode2 + i);
511  WorkMat.PutColIndex(i + 6, iFirstPositionIndexNode2 + i);
512  }
513 
514  for (integer i = 1; i <= iNumDof; ++i) {
515  WorkMat.PutRowIndex(12 + i, iFirstIndex + i);
516  WorkMat.PutColIndex(12 + i, iFirstIndex + i);
517  }
518 
519  const Vec3& X1 = pNode1->GetXCurr();
520  const Mat3x3& R1 = pNode1->GetRCurr();
521  const Mat3x3& R1_0 = pNode1->GetRRef();
522  const Vec3& X2 = pNode2->GetXCurr();
523  const Mat3x3& R2 = pNode2->GetRCurr();
524  const Mat3x3& R2_0 = pNode2->GetRRef();
525 
526  // common subexpressions
527  const Vec3 R1e1 = R1 * e.GetCol(1);
528  const Vec3 R1e2 = R1 * e.GetCol(2);
529  const Vec3 R1e3 = R1 * e.GetCol(3);
530  const Vec3 R2o2 = R2 * o2;
531  const Vec3 R2_0o2 = R2_0 * o2;
532  const Vec3 l1 = X2 + R2o2 - X1;
533 
534  const Vec3& XP1 = pNode1->GetVCurr();
535  const Vec3& omega1 = pNode1->GetWCurr();
536  const Vec3& omega1_0 = pNode1->GetWRef();
537  const Vec3& XP2 = pNode2->GetVCurr();
538  const Vec3& omega2 = pNode2->GetWCurr();
539 
540  const doublereal DeltaXP = SlidingVelocity(X1, R1, XP1, omega1, X2, R2, XP2, omega2);
541  const Vec3 dDeltaXP_dX1_T = -omega1.Cross(R1e1);
542  const Vec3 dDeltaXP_dg1_T = -(XP2 + omega2.Cross(R2o2) - XP1 - omega1.Cross(l1)).Cross(R1_0 * e.GetCol(1))
543  - omega1_0.Cross((l1).Cross(R1e1));
544  const Vec3 dDeltaXP_dXP1_T = -R1e1;
545  const Vec3 dDeltaXP_dgP1_T = -l1.Cross(R1e1);
546  const Vec3 dDeltaXP_dX2_T = omega1.Cross(R1e1);
547  const Vec3 dDeltaXP_dg2_T = R2_0o2.Cross((omega1 - omega2).Cross(R1e1)) + omega2.Cross(R2o2.Cross(R1e1));
548  const Vec3& dDeltaXP_dXP2_T = R1e1;
549  const Vec3 dDeltaXP_dgP2_T = R2o2.Cross(R1e1);
550 
551  const doublereal tau = FrictionForce(DeltaXP);
552  doublereal dtau_dDeltaXP = kv;
553  doublereal dtau_dlambda[2];
554 
555  if (muc > 0)
556  {
557  const doublereal mu = FrictionCoefficient(DeltaXP);
558  const doublereal lambda_res = NormalForceMagnitude();
559 
560  dtau_dDeltaXP -= muc * lambda_res * z / delta * (mus / muc - 1) * exp(-std::pow(std::abs(DeltaXP) / vs, iv))
561  * iv * std::pow(std::abs(DeltaXP) / vs, iv - 1) * copysign(1., DeltaXP) / vs;
562 
563  if (lambda_res != 0) {
564  for (int i = 0; i < 2; ++i) {
565  dtau_dlambda[i] = mu * lambda[i] * z / (lambda_res * delta);
566  }
567  } else { // avoid division by zero
568  for (int i = 0; i < 2; ++i) {
569  dtau_dlambda[i] = mu * copysign(1., lambda[i]) * z / delta;
570  }
571  }
572 
573  const doublereal dtau_dz = mu * lambda_res / delta;
574  const Vec3 dF1_dz = R1e1 * dtau_dz;
575  const Vec3 dM1_dz = l1.Cross(dF1_dz);
576  const Vec3 dM2_dz = (-R2o2).Cross(dF1_dz);
577 
578  const doublereal alpha = z / delta * copysign(1., DeltaXP) - 1;
579 
580  const Vec3 dPhi_dX1_T = dDeltaXP_dX1_T * alpha;
581  const Vec3 dPhi_dg1_T = dDeltaXP_dg1_T * alpha;
582  const Vec3 dPhi_dXP1_T = dDeltaXP_dXP1_T * alpha;
583  const Vec3 dPhi_dgP1_T = dDeltaXP_dgP1_T * alpha;
584  const Vec3 dPhi_dX2_T = dDeltaXP_dX2_T * alpha;
585  const Vec3 dPhi_dg2_T = dDeltaXP_dg2_T * alpha;
586  const Vec3 dPhi_dXP2_T = dDeltaXP_dXP2_T * alpha;
587  const Vec3 dPhi_dgP2_T = dDeltaXP_dgP2_T * alpha;
588 
589  const doublereal dPhi_dz = std::abs(DeltaXP) / delta;
590  const doublereal dPhi_dzP = 1.;
591 
592  WorkMat.Put(1, 15, -dF1_dz * dCoef);
593  WorkMat.Put(4, 15, -dM1_dz * dCoef);
594  WorkMat.Put(7, 15, dF1_dz * dCoef);
595  WorkMat.Put(10, 15, -dM2_dz * dCoef);
596  WorkMat.PutT(15, 1, (dPhi_dXP1_T + dPhi_dX1_T * dCoef) * (-PhiScale));
597  WorkMat.PutT(15, 4, (dPhi_dgP1_T + dPhi_dg1_T * dCoef) * (-PhiScale));
598  WorkMat.PutT(15, 7, (dPhi_dXP2_T + dPhi_dX2_T * dCoef) * (-PhiScale));
599  WorkMat.PutT(15, 10, (dPhi_dgP2_T + dPhi_dg2_T * dCoef) * (-PhiScale));
600  WorkMat.PutCoef(15, 15, (dPhi_dzP + dPhi_dz * dCoef) * (-PhiScale));
601  }
602  else
603  {
604  for (int i = 0; i < 2; ++i)
605  {
606  dtau_dlambda[i] = 0;
607  }
608  }
609 
610  const Vec3 dtau_dX1_T = dDeltaXP_dX1_T * dtau_dDeltaXP;
611  const Vec3 dtau_dg1_T = dDeltaXP_dg1_T * dtau_dDeltaXP;
612  const Vec3 dtau_dXP1_T = dDeltaXP_dXP1_T * dtau_dDeltaXP;
613  const Vec3 dtau_dgP1_T = dDeltaXP_dgP1_T * dtau_dDeltaXP;
614  const Vec3 dtau_dX2_T = dDeltaXP_dX2_T * dtau_dDeltaXP;
615  const Vec3 dtau_dg2_T = dDeltaXP_dg2_T * dtau_dDeltaXP;
616  const Vec3 dtau_dXP2_T = dDeltaXP_dXP2_T * dtau_dDeltaXP;
617  const Vec3 dtau_dgP2_T = dDeltaXP_dgP2_T * dtau_dDeltaXP;
618 
619  const Vec3 F1 = R1e1 * tau + R1e2 * lambda[L1] + R1e3 * lambda[L2];
620  const Vec3 M1 = l1.Cross(F1);
621 
622  const Mat3x3 dF1_dX1 = R1e1.Tens(dtau_dX1_T);
623  const Mat3x3 dF1_dg1 = R1e1.Tens(dtau_dg1_T) - Mat3x3(MatCross, R1_0 * (e.GetCol(1) * tau + e.GetCol(2) * lambda[L1] + e.GetCol(3) * lambda[L2]));
624  const Mat3x3 dF1_dXP1 = R1e1.Tens(dtau_dXP1_T);
625  const Mat3x3 dF1_dgP1 = R1e1.Tens(dtau_dgP1_T);
626  const Mat3x3 dF1_dX2 = R1e1.Tens(dtau_dX2_T);
627  const Mat3x3 dF1_dg2 = R1e1.Tens(dtau_dg2_T);
628  const Mat3x3 dF1_dXP2 = R1e1.Tens(dtau_dXP2_T);
629  const Mat3x3 dF1_dgP2 = R1e1.Tens(dtau_dgP2_T);
630  const Vec3 dF1_dlambda1 = R1e1 * dtau_dlambda[L1] + R1e2;
631  const Vec3 dF1_dlambda2 = R1e1 * dtau_dlambda[L2] + R1e3;
632 
633  const Mat3x3 dM1_dX1 = l1.Cross(dF1_dX1) + Mat3x3(MatCross, F1);
634  const Mat3x3 dM1_dg1 = l1.Cross(dF1_dg1);
635  const Mat3x3 dM1_dXP1 = l1.Cross(dF1_dXP1);
636  const Mat3x3 dM1_dgP1 = l1.Cross(dF1_dgP1);
637  const Mat3x3 dM1_dX2 = l1.Cross(dF1_dX2) - Mat3x3(MatCross, F1);
638  const Mat3x3 dM1_dg2 = l1.Cross(dF1_dg2) + Mat3x3(MatCrossCross, F1, R2_0o2);
639  const Mat3x3 dM1_dXP2 = l1.Cross(dF1_dXP2);
640  const Mat3x3 dM1_dgP2 = l1.Cross(dF1_dgP2);
641  const Vec3 dM1_dlambda1 = l1.Cross(dF1_dlambda1);
642  const Vec3 dM1_dlambda2 = l1.Cross(dF1_dlambda2);
643 
644  const Mat3x3 dM2_dX1 = (-R2o2).Cross(dF1_dX1);
645  const Mat3x3 dM2_dg1 = (-R2o2).Cross(dF1_dg1);
646  const Mat3x3 dM2_dXP1 = (-R2o2).Cross(dF1_dXP1);
647  const Mat3x3 dM2_dgP1 = (-R2o2).Cross(dF1_dgP1);
648  const Mat3x3 dM2_dX2 = (-R2o2).Cross(dF1_dX2);
649  const Mat3x3 dM2_dg2 = Mat3x3(MatCrossCross, -F1, R2_0o2) - R2o2.Cross(dF1_dg2);
650  const Mat3x3 dM2_dXP2 = (-R2o2).Cross(dF1_dXP2);
651  const Mat3x3 dM2_dgP2 = (-R2o2).Cross(dF1_dgP2);
652  const Vec3 dM2_dlambda1 = (-R2o2).Cross(dF1_dlambda1);
653  const Vec3 dM2_dlambda2 = (-R2o2).Cross(dF1_dlambda2);
654 
655  const Vec3 dc1_dX1_T = -R1e2;
656  const Vec3 dc1_dg1_T = -l1.Cross(R1_0 * e.GetCol(2));
657  const Vec3& dc1_dX2_T = R1e2;
658  const Vec3 dc1_dg2_T = R2_0o2.Cross(R1e2);
659 
660  const Vec3 dc2_dX1_T = -R1e3;
661  const Vec3 dc2_dg1_T = -l1.Cross(R1_0 * e.GetCol(3));
662  const Vec3& dc2_dX2_T = R1e3;
663  const Vec3 dc2_dg2_T = R2_0o2.Cross(R1e3);
664 
665  WorkMat.Put(1, 1, -dF1_dXP1 - dF1_dX1 * dCoef);
666  WorkMat.Put(1, 4, -dF1_dgP1 - dF1_dg1 * dCoef);
667  WorkMat.Put(1, 7, -dF1_dXP2 - dF1_dX2 * dCoef);
668  WorkMat.Put(1, 10, -dF1_dgP2 - dF1_dg2 * dCoef);
669  WorkMat.Put(1, 13, -dF1_dlambda1);
670  WorkMat.Put(1, 14, -dF1_dlambda2);
671 
672  WorkMat.Put(4, 1, -dM1_dXP1 - dM1_dX1 * dCoef);
673  WorkMat.Put(4, 4, -dM1_dgP1 - dM1_dg1 * dCoef);
674  WorkMat.Put(4, 7, -dM1_dXP2 - dM1_dX2 * dCoef);
675  WorkMat.Put(4, 10, -dM1_dgP2 - dM1_dg2 * dCoef);
676  WorkMat.Put(4, 13, -dM1_dlambda1);
677  WorkMat.Put(4, 14, -dM1_dlambda2);
678 
679  WorkMat.Put(7, 1, dF1_dXP1 + dF1_dX1 * dCoef);
680  WorkMat.Put(7, 4, dF1_dgP1 + dF1_dg1 * dCoef);
681  WorkMat.Put(7, 7, dF1_dXP2 + dF1_dX2 * dCoef);
682  WorkMat.Put(7, 10, dF1_dgP2 + dF1_dg2 * dCoef);
683  WorkMat.Put(7, 13, dF1_dlambda1);
684  WorkMat.Put(7, 14, dF1_dlambda2);
685 
686  WorkMat.Put(10, 1, -dM2_dXP1 - dM2_dX1 * dCoef);
687  WorkMat.Put(10, 4, -dM2_dgP1 - dM2_dg1 * dCoef);
688  WorkMat.Put(10, 7, -dM2_dXP2 - dM2_dX2 * dCoef);
689  WorkMat.Put(10, 10, -dM2_dgP2 - dM2_dg2 * dCoef);
690  WorkMat.Put(10, 13, -dM2_dlambda1);
691  WorkMat.Put(10, 14, -dM2_dlambda2);
692 
693  WorkMat.PutT(13, 1, -dc1_dX1_T);
694  WorkMat.PutT(13, 4, -dc1_dg1_T);
695  WorkMat.PutT(13, 7, -dc1_dX2_T);
696  WorkMat.PutT(13, 10, -dc1_dg2_T);
697 
698  WorkMat.PutT(14, 1, -dc2_dX1_T);
699  WorkMat.PutT(14, 4, -dc2_dg1_T);
700  WorkMat.PutT(14, 7, -dc2_dX2_T);
701  WorkMat.PutT(14, 10, -dc2_dg2_T);
702 
703  return WorkMatVar;
704 }
705 
706 
709  doublereal dCoef,
710  const VectorHandler& XCurr,
711  const VectorHandler& XPrimeCurr)
712 {
713  integer iNumRows, iNumCols;
714  WorkSpaceDim(&iNumRows, &iNumCols);
715  WorkVec.ResizeReset(iNumRows);
716 
717  const integer iFirstMomentumIndexNode1 = pNode1->iGetFirstMomentumIndex();
718  const integer iFirstMomentumIndexNode2 = pNode2->iGetFirstMomentumIndex();
719  const integer iFirstIndex = iGetFirstIndex();
720  const integer iNumDof = iGetNumDof();
721 
722  for (integer i = 1; i <= 6; ++i) {
723  WorkVec.PutRowIndex(i, iFirstMomentumIndexNode1 + i);
724  WorkVec.PutRowIndex(i + 6, iFirstMomentumIndexNode2 + i);
725  }
726 
727  for (integer i = 1; i <= iNumDof; ++i) {
728  WorkVec.PutRowIndex(i + 12, iFirstIndex + i);
729  }
730 
731  for (int i = 1; i <= 2; ++i)
732  lambda[i - 1] = XCurr(iFirstIndex + i);
733 
734  const Vec3& X1 = pNode1->GetXCurr();
735  const Mat3x3& R1 = pNode1->GetRCurr();
736  const Vec3& X2 = pNode2->GetXCurr();
737  const Mat3x3& R2 = pNode2->GetRCurr();
738 
739  const Vec3 R2o2 = R2 * o2;
740  const Vec3 l1 = X2 + R2o2 - X1;
741 
742  const Vec3& XP1 = pNode1->GetVCurr();
743  const Vec3& omega1 = pNode1->GetWCurr();
744  const Vec3& XP2 = pNode2->GetVCurr();
745  const Vec3& omega2 = pNode2->GetWCurr();
746 
747  const doublereal DeltaXP = SlidingVelocity(X1, R1, XP1, omega1, X2, R2, XP2, omega2);
748 
749  if (muc > 0)
750  {
751  z = XCurr(iFirstIndex + 3); // Attention: update z before calling FrictionForce!
752  zP = XPrimeCurr(iFirstIndex + 3);
753 
754  const doublereal Phi = zP - DeltaXP * (1. - z / delta * copysign(1., DeltaXP));
755 
756  WorkVec.PutCoef(15, Phi * PhiScale);
757  }
758 
759  const doublereal tau = FrictionForce(DeltaXP);
760 
761  const Vec3 F1 = R1 * ( e.GetCol(1) * tau + e.GetCol(2) * lambda[L1] + e.GetCol(3) * lambda[L2] );
762  const Vec3 M1 = l1.Cross(F1);
763  const Vec3 F2 = -F1;
764  const Vec3 M2 = R2o2.Cross(F2);
765 
766  const Vec3 a = R1.MulTV(l1) - o1;
767 
768  WorkVec.Put(1, F1);
769  WorkVec.Put(4, M1);
770  WorkVec.Put(7, F2);
771  WorkVec.Put(10, M2);
772 
773  for (int i = 1; i <= 2; ++i) {
774  WorkVec.PutCoef(12 + i, e.GetCol(i + 1).Dot(a) / dCoef);
775  }
776 
777  return WorkVec;
778 }
779 
780 int
782 {
783  return 2;
784 }
785 
786 void
787 InlineFriction::GetConnectedNodes(std::vector<const Node *>& connectedNodes) const
788 {
789  connectedNodes.resize(iGetNumConnectedNodes());
790  connectedNodes[0] = pNode1;
791  connectedNodes[1] = pNode2;
792 }
793 
794 void
798 {
799  const integer iFirstIndex = iGetFirstIndex();
800 
801  for (int i = 1; i <= 2; ++i)
802  X.PutCoef(iFirstIndex + i, lambda[i - 1]);
803 
804  if (muc > 0)
805  {
806  X.PutCoef(iFirstIndex + 3, z);
807  XP.PutCoef(iFirstIndex + 3, zP);
808  }
809 }
810 
811 std::ostream&
812 InlineFriction::Restart(std::ostream& out) const
813 {
814  return out;
815 }
816 
817 unsigned int
819 {
820  return 4;
821 }
822 
823 void
825  integer* piNumRows,
826  integer* piNumCols) const
827 {
828  *piNumRows = *piNumCols = 28;
829 }
830 
833  VariableSubMatrixHandler& WorkMatVar,
834  const VectorHandler& XCurr)
835 {
836  integer iNumRows, iNumCols;
837 
838  InitialWorkSpaceDim(&iNumRows, &iNumCols);
839 
840  FullSubMatrixHandler& WorkMat = WorkMatVar.SetFull();
841 
842  WorkMat.ResizeReset(iNumRows, iNumCols);
843 
844  const Vec3& X1 = pNode1->GetXCurr();
845  const Mat3x3& R1 = pNode1->GetRCurr();
846  const Mat3x3& R1_0 = pNode1->GetRRef();
847  const Vec3& XP1 = pNode1->GetVCurr();
848  const Vec3& omega1 = pNode1->GetWCurr();
849  const Vec3& X2 = pNode2->GetXCurr();
850  const Mat3x3& R2 = pNode2->GetRCurr();
851  const Mat3x3& R2_0 = pNode2->GetRRef();
852  const Vec3& XP2 = pNode2->GetVCurr();
853  const Vec3& omega2 = pNode2->GetWCurr();
854 
855  const integer iFirstIndexNode1 = pNode1->iGetFirstIndex();
856  const integer iFirstIndexNode2 = pNode2->iGetFirstIndex();
857  const integer iFirstIndex = iGetFirstIndex();
858 
859  for (integer i = 1; i <= 12; ++i) {
860  WorkMat.PutRowIndex(i, iFirstIndexNode1 + i);
861  WorkMat.PutColIndex(i, iFirstIndexNode1 + i);
862  WorkMat.PutRowIndex(i + 12, iFirstIndexNode2 + i);
863  WorkMat.PutColIndex(i + 12, iFirstIndexNode2 + i);
864  }
865 
866  for (integer i = 1; i <= 4; ++i) {
867  WorkMat.PutRowIndex(i + 24, iFirstIndex + i);
868  WorkMat.PutColIndex(i + 24, iFirstIndex + i);
869  }
870 
871  doublereal lambdaP[2];
872 
873  for (int i = 1; i <= 2; ++i) {
874  lambda[i - 1] = XCurr.dGetCoef(iFirstIndex + i);
875  lambdaP[i - 1] = XCurr.dGetCoef(iFirstIndex + i + 2);
876  }
877 
878  const Vec3 R1e2 = R1 * e.GetCol(2);
879  const Vec3 R1e3 = R1 * e.GetCol(3);
880  const Vec3 R2o2 = R2 * o2;
881  const Vec3 R2_0o2 = R2_0 * o2;
882  const Vec3 l1 = X2 + R2o2 - X1;
883  const Vec3 lP1 = XP2 + omega2.Cross(R2o2) - XP1;
884 
885  const Vec3 F1 = R1e2 * lambda[L1] + R1e3 * lambda[L2];
886  const Vec3 FP1 = omega1.Cross(R1 * (e.GetCol(2) * lambda[L1] + e.GetCol(3) * lambda[L2]))
887  + R1 * (e.GetCol(2) * lambdaP[L1] + e.GetCol(3) * lambdaP[L2]);
888  // const Vec3 F2 = -F1;
889 
890  const Mat3x3 dF1_dg1 = Mat3x3(MatCross, R1_0 * (e.GetCol(2) * (-lambda[L1]) + e.GetCol(3) * (-lambda[L2])));
891  const Vec3& dF1_dlambda1 = R1e2;
892  const Vec3& dF1_dlambda2 = R1e3;
893 
894  const Mat3x3 dM1_dX1 = Mat3x3(MatCross, F1);
895  const Mat3x3 dM1_dg1 = l1.Cross(dF1_dg1);
896  const Mat3x3 dM1_dX2 = -dM1_dX1;
897  const Mat3x3 dM1_dg2 = Mat3x3(MatCrossCross, F1, R2_0o2);
898  const Vec3 dM1_dlambda1 = l1.Cross(dF1_dlambda1);
899  const Vec3 dM1_dlambda2 = l1.Cross(dF1_dlambda2);
900 
901  const Mat3x3 dFP1_dg1 = Mat3x3(MatCrossCross, -omega1, R1_0 * ( e.GetCol(2) * lambda[L1] + e.GetCol(3) * lambda[L2]))
902  - Mat3x3(MatCross, R1_0 * ( e.GetCol(2) * lambdaP[L1] + e.GetCol(3) * lambdaP[L2]));
903  const Mat3x3 dFP1_domega1 = Mat3x3(MatCross, R1 * (e.GetCol(2) * (-lambda[L1]) + e.GetCol(3) * (-lambda[L2])));
904  const Vec3 dFP1_dlambda1 = omega1.Cross(R1e2);
905  const Vec3 dFP1_dlambda2 = omega1.Cross(R1e3);
906  const Vec3& dFP1_dlambdaP1 = R1e2;
907  const Vec3& dFP1_dlambdaP2 = R1e3;
908 
909  const Mat3x3 dMP1_dX1 = Mat3x3(MatCross, FP1);
910  const Mat3x3 dMP1_dg1 = lP1.Cross(dF1_dg1) + l1.Cross(dFP1_dg1);
911  const Mat3x3 dMP1_dXP1 = Mat3x3(MatCross, F1);
912  const Mat3x3 dMP1_domega1 = l1.Cross(dFP1_domega1);
913  const Mat3x3 dMP1_dX2 = Mat3x3(MatCross, -FP1);
914  const Mat3x3 dMP1_dg2 = (Mat3x3(MatCrossCross, F1, omega2) + Mat3x3(MatCross, FP1)).MulVCross(R2_0o2);
915  const Mat3x3 dMP1_dXP2 = Mat3x3(MatCross, -F1);
916  const Mat3x3 dMP1_domega2 = Mat3x3(MatCrossCross, F1, R2o2);
917  const Vec3 dMP1_dlambda1 = lP1.Cross(dF1_dlambda1) + l1.Cross(dFP1_dlambda1);
918  const Vec3 dMP1_dlambda2 = lP1.Cross(dF1_dlambda2) + l1.Cross(dFP1_dlambda2);
919  const Vec3 dMP1_dlambdaP1 = l1.Cross(dFP1_dlambdaP1);
920  const Vec3 dMP1_dlambdaP2 = l1.Cross(dFP1_dlambdaP2);
921 
922  const Mat3x3 dM2_dg1 = (-R2o2).Cross(dF1_dg1);
923  const Mat3x3 dM2_dg2 = Mat3x3(MatCrossCross, -F1, R2_0o2);
924  const Vec3 dM2_dlambda1 = R2o2.Cross(-dF1_dlambda1);
925  const Vec3 dM2_dlambda2 = R2o2.Cross(-dF1_dlambda2);
926 
927  const Mat3x3 dMP2_dg1 = (-omega2.Cross(R2o2)).Cross(dF1_dg1) - R2o2.Cross(dFP1_dg1);
928  const Mat3x3 dMP2_domega1 = (-R2o2).Cross(dFP1_domega1);
929  const Mat3x3 dMP2_dg2 = (Mat3x3(MatCrossCross, -F1, omega2) - Mat3x3(MatCross, FP1)).MulVCross(R2_0o2);
930  const Mat3x3 dMP2_domega2 = Mat3x3(MatCrossCross, -F1, R2o2);
931  const Vec3 dMP2_dlambda1 = (-omega2.Cross(R2o2)).Cross(dF1_dlambda1) - R2o2.Cross(dFP1_dlambda1);
932  const Vec3 dMP2_dlambda2 = (-omega2.Cross(R2o2)).Cross(dF1_dlambda2) - R2o2.Cross(dFP1_dlambda2);
933  const Vec3 dMP2_dlambdaP1 = -R2o2.Cross(dFP1_dlambdaP1);
934  const Vec3 dMP2_dlambdaP2 = -R2o2.Cross(dFP1_dlambdaP2);
935 
936  const Vec3 dc1_dX1_T = -R1e2;
937  const Vec3 dc1_dg1_T = -l1.Cross(R1_0 * e.GetCol(2));
938  const Vec3& dc1_dX2_T = R1e2;
939  const Vec3 dc1_dg2_T = R2_0o2.Cross(R1e2);
940 
941  const Vec3 dc2_dX1_T = -R1e3;
942  const Vec3 dc2_dg1_T = -l1.Cross(R1_0 * e.GetCol(3));
943  const Vec3& dc2_dX2_T = R1e3;
944  const Vec3 dc2_dg2_T = R2_0o2.Cross(R1e3);
945 
946  const Vec3 dcP1_dX1_T = -omega1.Cross(R1e2);
947  const Vec3 dcP1_dg1_T = (omega1.Cross(l1) - lP1).Cross(R1_0 * e.GetCol(2));
948  const Vec3 dcP1_dXP1_T = -R1e2;
949  const Vec3 dcP1_domega1_T = -l1.Cross(R1e2);
950  const Vec3 dcP1_dX2_T = omega1.Cross(R1e2);
951  const Vec3 dcP1_dg2_T = R2_0o2.Cross((omega1 - omega2).Cross(R1e2));
952  const Vec3& dcP1_dXP2_T = R1e2;
953  const Vec3 dcP1_domega2_T = R2o2.Cross(R1e2);
954 
955  const Vec3 dcP2_dX1_T = -omega1.Cross(R1e3);
956  const Vec3 dcP2_dg1_T = (omega1.Cross(l1) - lP1).Cross(R1_0 * e.GetCol(3));
957  const Vec3 dcP2_dXP1_T = -R1e3;
958  const Vec3 dcP2_domega1_T = -l1.Cross(R1e3);
959  const Vec3 dcP2_dX2_T = omega1.Cross(R1e3);
960  const Vec3 dcP2_dg2_T = R2_0o2.Cross((omega1 - omega2).Cross(R1e3));
961  const Vec3& dcP2_dXP2_T = R1e3;
962  const Vec3 dcP2_domega2_T = R2o2.Cross(R1e3);
963 
964  WorkMat.Put( 1, 4, -dF1_dg1);
965  WorkMat.Put( 1, 25, -dF1_dlambda1);
966  WorkMat.Put( 1, 26, -dF1_dlambda2);
967 
968  WorkMat.Put( 4, 1, -dM1_dX1);
969  WorkMat.Put( 4, 4, -dM1_dg1);
970  WorkMat.Put( 4, 13, -dM1_dX2);
971  WorkMat.Put( 4, 16, -dM1_dg2);
972  WorkMat.Put( 4, 25, -dM1_dlambda1);
973  WorkMat.Put( 4, 26, -dM1_dlambda2);
974 
975  WorkMat.Put( 7, 4, -dFP1_dg1);
976  WorkMat.Put( 7, 10, -dFP1_domega1);
977  WorkMat.Put( 7, 25, -dFP1_dlambda1);
978  WorkMat.Put( 7, 26, -dFP1_dlambda2);
979  WorkMat.Put( 7, 27, -dFP1_dlambdaP1);
980  WorkMat.Put( 7, 28, -dFP1_dlambdaP2);
981 
982  WorkMat.Put(10, 1, -dMP1_dX1);
983  WorkMat.Put(10, 4, -dMP1_dg1);
984  WorkMat.Put(10, 7, -dMP1_dXP1);
985  WorkMat.Put(10, 10, -dMP1_domega1);
986  WorkMat.Put(10, 13, -dMP1_dX2);
987  WorkMat.Put(10, 16, -dMP1_dg2);
988  WorkMat.Put(10, 19, -dMP1_dXP2);
989  WorkMat.Put(10, 22, -dMP1_domega2);
990  WorkMat.Put(10, 25, -dMP1_dlambda1);
991  WorkMat.Put(10, 26, -dMP1_dlambda2);
992  WorkMat.Put(10, 27, -dMP1_dlambdaP1);
993  WorkMat.Put(10, 28, -dMP1_dlambdaP2);
994 
995  WorkMat.Put(13, 4, dF1_dg1); // dF2_dg1 = -dF1_dg1
996  WorkMat.Put(13, 25, dF1_dlambda1);
997  WorkMat.Put(13, 26, dF1_dlambda2);
998 
999  WorkMat.Put(16, 4, -dM2_dg1);
1000  WorkMat.Put(16, 16, -dM2_dg2);
1001  WorkMat.Put(16, 25, -dM2_dlambda1);
1002  WorkMat.Put(16, 26, -dM2_dlambda2);
1003 
1004  WorkMat.Put(19, 4, dFP1_dg1);
1005  WorkMat.Put(19, 10, dFP1_domega1);
1006  WorkMat.Put(19, 25, dFP1_dlambda1);
1007  WorkMat.Put(19, 26, dFP1_dlambda2);
1008  WorkMat.Put(19, 27, dFP1_dlambdaP1);
1009  WorkMat.Put(19, 28, dFP1_dlambdaP2);
1010 
1011  WorkMat.Put(22, 4, -dMP2_dg1);
1012  WorkMat.Put(22, 10, -dMP2_domega1);
1013  WorkMat.Put(22, 16, -dMP2_dg2);
1014  WorkMat.Put(22, 22, -dMP2_domega2);
1015  WorkMat.Put(22, 25, -dMP2_dlambda1);
1016  WorkMat.Put(22, 26, -dMP2_dlambda2);
1017  WorkMat.Put(22, 27, -dMP2_dlambdaP1);
1018  WorkMat.Put(22, 28, -dMP2_dlambdaP2);
1019 
1020  WorkMat.PutT(25, 1, -dc1_dX1_T);
1021  WorkMat.PutT(25, 4, -dc1_dg1_T);
1022  WorkMat.PutT(25, 13, -dc1_dX2_T);
1023  WorkMat.PutT(25, 16, -dc1_dg2_T);
1024 
1025  WorkMat.PutT(26, 1, -dc2_dX1_T);
1026  WorkMat.PutT(26, 4, -dc2_dg1_T);
1027  WorkMat.PutT(26, 13, -dc2_dX2_T);
1028  WorkMat.PutT(26, 16, -dc2_dg2_T);
1029 
1030  WorkMat.PutT(27, 1, -dcP1_dX1_T);
1031  WorkMat.PutT(27, 4, -dcP1_dg1_T);
1032  WorkMat.PutT(27, 7, -dcP1_dXP1_T);
1033  WorkMat.PutT(27, 10, -dcP1_domega1_T);
1034  WorkMat.PutT(27, 13, -dcP1_dX2_T);
1035  WorkMat.PutT(27, 16, -dcP1_dg2_T);
1036  WorkMat.PutT(27, 19, -dcP1_dXP2_T);
1037  WorkMat.PutT(27, 22, -dcP1_domega2_T);
1038 
1039  WorkMat.PutT(28, 1, -dcP2_dX1_T);
1040  WorkMat.PutT(28, 4, -dcP2_dg1_T);
1041  WorkMat.PutT(28, 7, -dcP2_dXP1_T);
1042  WorkMat.PutT(28, 10, -dcP2_domega1_T);
1043  WorkMat.PutT(28, 13, -dcP2_dX2_T);
1044  WorkMat.PutT(28, 16, -dcP2_dg2_T);
1045  WorkMat.PutT(28, 19, -dcP2_dXP2_T);
1046  WorkMat.PutT(28, 22, -dcP2_domega2_T);
1047 
1048  return WorkMatVar;
1049 }
1050 
1053  SubVectorHandler& WorkVec,
1054  const VectorHandler& XCurr)
1055 {
1056  integer iNumRows, iNumCols;
1057 
1058  InitialWorkSpaceDim(&iNumRows, &iNumCols);
1059 
1060  WorkVec.ResizeReset(iNumRows);
1061 
1062  const Vec3& X1 = pNode1->GetXCurr();
1063  const Mat3x3& R1 = pNode1->GetRCurr();
1064  const Vec3& XP1 = pNode1->GetVCurr();
1065  const Vec3& omega1 = pNode1->GetWCurr();
1066  const Vec3& X2 = pNode2->GetXCurr();
1067  const Mat3x3& R2 = pNode2->GetRCurr();
1068  const Vec3& XP2 = pNode2->GetVCurr();
1069  const Vec3& omega2 = pNode2->GetWCurr();
1070 
1071  const integer iFirstIndexNode1 = pNode1->iGetFirstIndex();
1072  const integer iFirstIndexNode2 = pNode2->iGetFirstIndex();
1073  const integer iFirstIndex = iGetFirstIndex();
1074 
1075  for (integer i = 1; i <= 12; ++i) {
1076  WorkVec.PutRowIndex(i, iFirstIndexNode1 + i);
1077  WorkVec.PutRowIndex(i + 12, iFirstIndexNode2 + i);
1078  }
1079 
1080  for (integer i = 1; i <= 4; ++i) {
1081  WorkVec.PutRowIndex(i + 24, iFirstIndex + i);
1082  }
1083 
1084  doublereal lambdaP[2];
1085 
1086  for (int i = 1; i <= 2; ++i) {
1087  lambda[i - 1] = XCurr.dGetCoef(iFirstIndex + i);
1088  lambdaP[i - 1] = XCurr.dGetCoef(iFirstIndex + i + 2);
1089  }
1090 
1091  const Vec3 R2o2 = R2 * o2;
1092  const Vec3 l1 = X2 + R2o2 - X1;
1093 
1094  const Vec3 F1 = R1 * (e.GetCol(2) * lambda[L1] + e.GetCol(3) * lambda[L2]);
1095  const Vec3 M1 = l1.Cross(F1);
1096  const Vec3 FP1 = omega1.Cross(R1 * (e.GetCol(2) * lambda[L1] + e.GetCol(3) * lambda[L2]))
1097  + R1 * (e.GetCol(2) * lambdaP[L1] + e.GetCol(3) * lambdaP[L2]);
1098  const Vec3 MP1 = -F1.Cross(XP2 + omega2.Cross(R2o2) - XP1) + l1.Cross(FP1);
1099  const Vec3 F2 = -F1;
1100  const Vec3 M2 = R2o2.Cross(F2);
1101  const Vec3 FP2 = -FP1;
1102  const Vec3 MP2 = (omega2.Cross(R2o2)).Cross(F2) + R2o2.Cross(FP2);
1103 
1104  const Vec3 a = R1.MulTV(l1) - o1;
1105  const Vec3 aP = R1.MulTV(l1.Cross(omega1) + XP2 + omega2.Cross(R2o2) - XP1);
1106 
1107  WorkVec.Put( 1, F1);
1108  WorkVec.Put( 4, M1);
1109  WorkVec.Put( 7, FP1);
1110  WorkVec.Put(10, MP1);
1111  WorkVec.Put(13, F2);
1112  WorkVec.Put(16, M2);
1113  WorkVec.Put(19, FP2);
1114  WorkVec.Put(22, MP2);
1115 
1116  for (int i = 1; i <= 2; ++i) {
1117  WorkVec.PutCoef(24 + i, e.GetCol(i + 1).Dot(a));
1118  WorkVec.PutCoef(26 + i, e.GetCol(i + 1).Dot(aP));
1119  }
1120 
1121  return WorkVec;
1122 }
1123 
1124 doublereal InlineFriction::SlidingVelocity(const Vec3& X1, const Mat3x3& R1, const Vec3& XP1, const Vec3& omega1, const Vec3& X2, const Mat3x3& R2, const Vec3& XP2, const Vec3& omega2) const
1125 {
1126  return e.GetCol(1).Dot(R1.MulTV(XP2 - (R2 * o2).Cross(omega2) - XP1 + (X2 + R2 * o2 - X1).Cross(omega1)));
1127 }
1128 
1130 {
1131  doublereal lambda_res = 0;
1132 
1133  for (int i = 0; i < 2; ++i)
1134  lambda_res += std::pow(lambda[i], 2);
1135 
1136  lambda_res = sqrt(lambda_res);
1137 
1138  return lambda_res;
1139 }
1140 
1142 {
1143  return muc > 0 ? (1. + (mus / muc - 1.) * exp(-std::pow(std::abs(DeltaXP) / vs, iv))) * muc : 0;
1144 }
1145 
1147 {
1148  const doublereal mu = FrictionCoefficient(DeltaXP);
1149  const doublereal lambda_res = NormalForceMagnitude();
1150  const doublereal tau = mu * lambda_res * z / delta + kv * DeltaXP;
1151 
1152  return tau;
1153 }
1154 
1156 {
1158 
1159  if (!SetUDE("inline" "friction", rf))
1160  {
1161  delete rf;
1162  return false;
1163  }
1164 
1165  return true;
1166 }
1167 
1168 #ifndef STATIC_MODULES
1169 
1170 extern "C"
1171 {
1172 
1173 int module_init(const char *module_name, void *pdm, void *php)
1174 {
1175  if (!inline_friction_set())
1176  {
1177  silent_cerr("inline friction: "
1178  "module_init(" << module_name << ") "
1179  "failed" << std::endl);
1180 
1181  return -1;
1182  }
1183 
1184  return 0;
1185 }
1186 
1187 }
1188 
1189 #endif // ! STATIC_MODULE
flag fReadOutput(MBDynParser &HP, const T &t) const
Definition: dataman.h:1064
virtual doublereal dGetPrivData(unsigned int i) const
GradientExpression< UnaryExpr< FuncExp, Expr > > exp(const GradientExpression< Expr > &u)
Definition: gradient.h:2975
Mat3x3 GetRotRel(const ReferenceFrame &rf)
Definition: mbpar.cc:1795
void PutColIndex(integer iSubCol, integer iCol)
Definition: submat.h:325
const Vec3 Zero3(0., 0., 0.)
Vec3 Cross(const Vec3 &v) const
Definition: matvec3.h:218
virtual DofOrder::Order GetEqType(unsigned int i) const
long int flag
Definition: mbdyn.h:43
virtual const Mat3x3 & GetRRef(void) const
Definition: strnode.h:1006
virtual bool bToBeOutput(void) const
Definition: output.cc:890
virtual unsigned int iGetPrivDataIdx(const char *s) const
GradientExpression< BinaryExpr< FuncPow, LhsExpr, RhsExpr > > pow(const GradientExpression< LhsExpr > &u, const GradientExpression< RhsExpr > &v)
Definition: gradient.h:2961
#define MBDYN_EXCEPT_ARGS
Definition: except.h:63
Definition: matvec3.h:98
virtual void ResizeReset(integer)
Definition: vh.cc:55
const MatCross_Manip MatCross
Definition: matvec3.cc:639
FullSubMatrixHandler & SetFull(void)
Definition: submat.h:1168
virtual const Mat3x3 & GetRCurr(void) const
Definition: strnode.h:1012
void PutT(integer iRow, integer iCol, const Vec3 &v)
Definition: submat.cc:239
bool inline_friction_set(void)
std::ostream & Restart(std::ostream &out) const
doublereal Dot(const Vec3 &v) const
Definition: matvec3.h:243
InlineFriction(unsigned uLabel, const DofOwner *pDO, DataManager *pDM, MBDynParser &HP)
virtual unsigned int iGetNumPrivData(void) const
void Put(integer iRow, integer iCol, const Vec3 &v)
Definition: submat.cc:221
VariableSubMatrixHandler & AssJac(VariableSubMatrixHandler &WorkMat, doublereal dCoef, const VectorHandler &XCurr, const VectorHandler &XPrimeCurr)
virtual ~InlineFriction(void)
const Mat3x3 Eye3(1., 0., 0., 0., 1., 0., 0., 0., 1.)
void PutCoef(integer iRow, integer iCol, const doublereal &dCoef)
Definition: submat.h:672
Vec3 GetCol(unsigned short int i) const
Definition: matvec3.h:903
doublereal FrictionCoefficient(doublereal DeltaXP) const
virtual void WorkSpaceDim(integer *piNumRows, integer *piNumCols) const
virtual const doublereal & dGetCoef(integer iRow) const =0
virtual const Vec3 & GetWRef(void) const
Definition: strnode.h:1024
doublereal FrictionForce(doublereal DeltaXP) const
std::vector< Hint * > Hints
Definition: simentity.h:89
virtual void InitialWorkSpaceDim(integer *piNumRows, integer *piNumCols) const
Vec3 MulTV(const Vec3 &v) const
Definition: matvec3.cc:482
virtual void PutRowIndex(integer iSubRow, integer iRow)=0
int iGetNumConnectedNodes(void) const
SubVectorHandler & InitialAssRes(SubVectorHandler &WorkVec, const VectorHandler &XCurr)
virtual std::ostream & DescribeDof(std::ostream &out, const char *prefix, bool bInitial) const
void SetValue(DataManager *pDM, VectorHandler &X, VectorHandler &XP, SimulationEntity::Hints *ph)
void GetConnectedNodes(std::vector< const Node * > &connectedNodes) const
Vec3 GetPosRel(const ReferenceFrame &rf)
Definition: mbpar.cc:1331
int module_init(const char *module_name, void *pdm, void *php)
This function registers our user defined element for the math parser.
virtual bool IsKeyWord(const char *sKeyWord)
Definition: parser.cc:910
std::ostream & Loadable(void) const
Definition: output.h:506
SubVectorHandler & AssRes(SubVectorHandler &WorkVec, doublereal dCoef, const VectorHandler &XCurr, const VectorHandler &XPrimeCurr)
doublereal copysign(doublereal x, doublereal y)
Definition: gradient.h:97
virtual DofOrder::Order GetDofType(unsigned int i) const
doublereal SlidingVelocity(const Vec3 &X1, const Mat3x3 &R1, const Vec3 &XP1, const Vec3 &omega1, const Vec3 &X2, const Mat3x3 &R2, const Vec3 &XP2, const Vec3 &omega2) const
virtual integer iGetFirstMomentumIndex(void) const =0
virtual integer iGetFirstPositionIndex(void) const
Definition: strnode.h:452
virtual const Vec3 & GetWCurr(void) const
Definition: strnode.h:1030
doublereal NormalForceMagnitude() const
unsigned int uLabel
Definition: withlab.h:44
virtual unsigned int iGetNumDof(void) const
#define ASSERT(expression)
Definition: colamd.c:977
Mat3x3 Tens(const Vec3 &v) const
Definition: matvec3.cc:53
GradientExpression< UnaryExpr< FuncSqrt, Expr > > sqrt(const GradientExpression< Expr > &u)
Definition: gradient.h:2974
VariableSubMatrixHandler & InitialAssJac(VariableSubMatrixHandler &WorkMat, const VectorHandler &XCurr)
virtual std::ostream & DescribeEq(std::ostream &out, const char *prefix, bool bInitial) const
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)
Definition: matvec.h:3248
virtual const Vec3 & GetXCurr(void) const
Definition: strnode.h:310
virtual void Output(OutputHandler &OH) const
virtual void ResizeReset(integer, integer)
Definition: submat.cc:182
Definition: except.h:79
const MatCrossCross_Manip MatCrossCross
Definition: matvec3.cc:640
virtual void Put(integer iRow, const Vec3 &v)
Definition: vh.cc:93
virtual bool IsArg(void)
Definition: parser.cc:807
Definition: elem.h:75
void PutRowIndex(integer iSubRow, integer iRow)
Definition: submat.h:311
std::ostream & GetLogFile(void) const
Definition: dataman.h:326
bool SetUDE(const std::string &s, UserDefinedElemRead *rude)
Definition: userelem.cc:97
virtual unsigned int iGetInitialNumDof(void) const
virtual const Vec3 & GetVCurr(void) const
Definition: strnode.h:322
static const doublereal a
Definition: hfluid_.h:289
virtual void SetOutputFlag(flag f=flag(1))
Definition: output.cc:896
virtual integer iGetFirstIndex(void) const
Definition: dofown.h:127
double doublereal
Definition: colamd.c:52
long int integer
Definition: colamd.c:51
virtual HighParser::ErrOut GetLineData(void) const
Definition: parsinc.cc:697
unsigned int GetLabel(void) const
Definition: withlab.cc:62
Node * ReadNode(MBDynParser &HP, Node::Type type) const
Definition: dataman3.cc:2309
bool UseText(int out) const
Definition: output.cc:446
virtual doublereal GetReal(const doublereal &dDefval=0.0)
Definition: parser.cc:1056