MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
shockabsorber.h
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/shockabsorber.h,v 1.46 2017/01/12 14:46:10 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32 /*
33  * Copyright (C) 1985-2017 GRAALL
34  *
35  * Gian Luca Ghiringhelli <ghiringhelli@aero.polimi.it>
36  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
37  * via La Masa, 34 - 20156 Milano, Italy
38  * http://www.aero.polimi.it
39  */
40 
41 #ifndef SHOCKABSORBER_H
42 #define SHOCKABSORBER_H
43 
44 #include "constltp.h"
45 
50 
51 /* ShockAbsorberConstitutiveLaw - begin */
52 
53 template <class T, class Tder>
55 : public ElasticConstitutiveLaw<T, Tder> {
56 private:
57 
58 public:
60  const DataManager* pDM,
61  TplDriveCaller<T>* pDC,
62  MBDynParser& HP
63  ) : ElasticConstitutiveLaw<T, Tder>(pDC, 0.) {
65  };
66 
67  virtual
69  NO_OP;
70  };
71 
73  pCopy(void) const {
74  return NULL;
75  };
76 
77  virtual std::ostream&
78  Restart(std::ostream& out) const {
79  return out
80  << "/* Shock absorber, not implemented yet */"
81  << std::endl;
82  };
83 
84  virtual void
85  Update(const T& /* Eps */ , const T& /* EpsPrime */ = 0.) {
86  NO_OP;
87  };
88 };
89 
90 
91 template<>
93 : public ElasticConstitutiveLaw<doublereal, doublereal> {
94 private:
95  /*
96  * Il legame costitutivo scalare riceve in ingresso
97  * la "deformazione", ovvero la relazione
98  *
99  * l - l0
100  * epsilon = --------
101  * l0
102  *
103  * Per comodita' dell'utente, si prende come lunghezza
104  * di riferimento la distanza tra i punti estremi
105  * dell'ammortizzatore, l0.
106  * Se si parte da una condizione diversa da completamente
107  * esteso, occorre aggiungere una deformazione iniziale.
108  *
109  * Il volume della camera e' calcolato come:
110  *
111  * V = l0 * ( 1 + Cint * epsilon ) * A0
112  *
113  * dove Cint e' un coefficiente di interazione che lega la
114  * corsa esterna del pistone alla effettiva variazione di
115  * lunghezza della camera.
116  * Il rapporto tra i volumi iniziale e istantaneo e'
117  *
118  * V0 1
119  * --- = -------------------
120  * V 1 + Cint * epsilon
121  *
122  * La forza e' calcolata mediante una politropica:
123  *
124  * V0
125  * F = A0 * P0 * ( ---- )^gamma
126  * V
127  */
128 
129  /*
130  * Parte elastica
131  */
136 
137  /*
138  * Limiti e fine-corsa con penalty function
139  */
144  bool bPenalty;
145 
146  /*
147  * Dissipazione
148  */
152 
154  doublereal RhoFluid; /* FIXME: usare i fluidi idraulici? */
156 
159 
160  /*
161  * Dati necessari per output/priv data
162  */
167 
168  /*
169  * Costruttore per pCopy
170  */
174  p->pGetDriveCaller()->pCopy(),
175  0.
176  ) {
177  P0 = p->P0;
178  A0 = p->A0;
179  Cint = p->Cint;
180  Gamma = p->Gamma;
181 
182  EpsMax = p->EpsMax;
183  EpsMin = p->EpsMin;
184  Penalty = p->Penalty;
185  PenaltyPrime = p->PenaltyPrime;
186 #if 0
187  FMax = p->FMax;
188  FMin = p->FMin;
189 #endif
190 
191  pAreaPinPlus = p->pAreaPinPlus->pCopy();
192  pAreaPinMinus = p->pAreaPinMinus->pCopy();
193  pAreaOrifices = p->pAreaOrifices->pCopy();
194 
195  AreaFluid = p->AreaFluid;
196  RhoFluid = p->RhoFluid;
197  Cd = p->Cd;
198 
199  EpsPrimeRef = p->EpsPrimeRef;
200  FrictionAmpl = p->FrictionAmpl;
201  };
202 
203 public:
205  const DataManager* pDM,
207  MBDynParser& HP
209  EpsMax(defaultEpsMax), EpsMin(defaultEpsMin),
210  Penalty(defaultPenalty), PenaltyPrime(defaultPenaltyPrime),
211  bPenalty(false),
212  pAreaPinPlus(NULL), pAreaPinMinus(NULL), pAreaOrifices(NULL),
213  EpsPrimeRef(1.), FrictionAmpl(0.), dPressure(0.) {
214  if (HP.IsKeyWord("help")) {
215 
216  silent_cout(
217 "\n"
218 "this help refers to the specific \"shock absorber\" constitutive\n"
219 "law input data. The prestrain value, if required, must be inserted\n"
220 "at the beginning of the data. The syntax is:\n"
221 "\n"
222 "\t[ prestrain , <value> , ]\n"
223 "\t<reference pressure> ,\n"
224 "\t<reference area for force computation> ,\n"
225 "\t<interaction coefficient (kinematic scale * ( L * A / V0 ) )> ,\n"
226 "\t<gamma (polytropic exponent)> ,\n"
227 "\t[ epsilon max , <upper strain bound, > prestrain; defaults to " << defaultEpsMax << ")> , ]\n"
228 "\t[ epsilon min , <lower strain bound, < prestrain; defaults to " << defaultEpsMin << ")> , ]\n"
229 "\t[ penalty , <penalty factor for strain bound enforcement, defaults to " << defaultPenalty << "> ,\n"
230 "\t\t<penalty factor for strain rate, active only when strain bounds are violated; defaults to " << defaultPenaltyPrime << "> ]\n"
231 "\t[ metering , <metering area (drive, strain dependent)> ,\n"
232 "\t\t[ negative , <metering area for negative strain rate (drive, strain dependent); same as above if not given> , ] ]\n"
233 "\t[ orifice , <orifice area (drive, strain rate dependent)> , ]\n"
234 "\t<fluid area> ,\n"
235 "\t<fluid density> ,\n"
236 "\t<drag coefficient / reference length (scales strain rate to velocity)>\n"
237 "\t[ , friction, <reference epsilon prime> ,\n"
238 "\t\t <friction amplitude coefficient> ] ;\n"
239 "\n"
240 "Note: at least one of \"metering\" and \"orifice\" must be defined.\n"
241 "Note: if 'friction' is enabled, the elastic force is multiplied\n"
242 " by the factor\n"
243 "\n"
244 "\t\t1. - <friction amplitude coefficient> * tanh( <epsilon prime> / <reference epsilon prime> )\n"
245 "\n"
246 "\toutput appended to output from element;\n"
247 "\t\trod joint:\n"
248 "\t\t\tcolumn 19: gas pressure\n"
249 "\t\t\tcolumn 20: metering area\n"
250 "\t\t\tcolumn 21: elastic force\n"
251 "\t\t\tcolumn 22: viscous force\n"
252 "\n"
253 "\toutput available as element private data; syntax:\n"
254 "\n"
255 "\t\t# in nodes data block\n"
256 "\t\tparameter: <parameter node label> , element ;\n"
257 "\t\t# in elements data block\n"
258 "\t\tbind: <rod label> , joint , <parameter node label> ,\n"
259 "\t\t\tstring , \"constitutiveLaw.<X>\" ;\n"
260 "\n"
261 "\twhere \"<X>\" can be:\n"
262 "\t\t\"p\": gas pressure\n"
263 "\t\t\"A\": metering area\n"
264 "\t\t\"Fe\": elastic force\n"
265 "\t\t\"Fv\": viscous force\n"
266 "\n"
267  << std::endl);
268 
269  if (!HP.IsArg()) {
270  /*
271  * Exit quietly if nothing else is provided
272  */
273  throw NoErr(MBDYN_EXCEPT_ARGS);
274  }
275 
276  }
277 
278  dPressure = P0 = HP.GetReal();
279  A0 = HP.GetReal();
280  Cint = HP.GetReal();
281  Gamma = HP.GetReal();
282 
283  if (HP.IsKeyWord("epsilon" "max")) {
284  EpsMax = HP.GetReal(defaultEpsMax);
285  }
286 
287  if (HP.IsKeyWord("epsilon" "min")) {
288  EpsMin = HP.GetReal(defaultEpsMin);
289  if (EpsMin >= EpsMax) {
290  silent_cerr("line " << HP.GetLineData()
291  << ": epsilon min must be less"
292  " than epsilon max" << std::endl);
294  }
295  }
296 
297  if (HP.IsKeyWord("penalty")) {
298  Penalty = HP.GetReal(defaultPenalty);
299  PenaltyPrime = HP.GetReal(defaultPenaltyPrime);
300  }
301 
302  if (HP.IsKeyWord("metering")) {
303  pAreaPinPlus = HP.GetDriveCaller();
304  if (HP.IsKeyWord("negative")) {
305  pAreaPinMinus = HP.GetDriveCaller();
306  } else {
307  pAreaPinMinus = pAreaPinPlus->pCopy();
308  }
309  }
310 
311  if (HP.IsKeyWord("orifice")) {
312  pAreaOrifices = HP.GetDriveCaller();
313  }
314 
315  if (pAreaPinPlus == NULL && pAreaOrifices == NULL) {
316  silent_cerr("line " << HP.GetLineData()
317  << ": at least one area (metering or orifice)"
318  " must be defined" << std::endl);
320  }
321 
322  AreaFluid = HP.GetReal();
323  RhoFluid = HP.GetReal();
324  Cd = HP.GetReal();
325 
326  if (HP.IsKeyWord("friction")) {
327  EpsPrimeRef = HP.GetReal();
328  if (EpsPrimeRef <= 0.) {
329  silent_cerr("Illegal Reference "
330  "Epsilon Prime " << EpsPrimeRef
331  << " at line " << HP.GetLineData()
332  << std::endl);
334  }
335 
336  FrictionAmpl = HP.GetReal();
337  if (FrictionAmpl < 0. || FrictionAmpl > 1.) {
338  silent_cerr("Illegal Friction "
339  "Amplitude Coefficient " << FrictionAmpl
340  << " at line " << HP.GetLineData()
341  << std::endl);
343  }
344  }
345 
346 #if 0
347  Update(EpsMax, 0.);
348  FMin = F;
349  Update(EpsMin, 0.);
350  FMax = F;
351 #endif
352  };
353 
354  virtual
356  NO_OP;
357  };
358 
360  pCopy(void) const {
362 
363  L* p = NULL;
364  SAFENEWWITHCONSTRUCTOR(p, L, L(this));
365  return p;
366  };
367 
368  virtual std::ostream&
369  Restart(std::ostream& out) const {
370 
371  /*
372  * FIXME: devo trovare il modo di ripristinare
373  * le deformazioni iniziali senza grossi danni :)
374  */
375  if (pGetDriveCaller()) {
376  out
377  << ", prestrain, single, ",
378  Write(out, -Epsilon, ", ") << ", one /* ",
379  pGetDriveCaller()->Restart(out) << " */ , ";
380  }
381 
382  /*
383  * dati sempre presenti
384  */
385  out
386  << P0 << ", "
387  << A0 << ", "
388  << Cint << ", "
389  << Gamma << ", "
390  << "epsilon max, " << EpsMax << ", "
391  << "epsilon min, " << EpsMin << ", "
392  << "penalty, " << Penalty << ", " << PenaltyPrime;
393 
394  /*
395  * drive delle aree (solo quelli definiti)
396  */
397  if (pAreaPinPlus) {
398  out
399  << ", metering, ",
400  pAreaPinPlus->Restart(out)
401  << ", negative, ",
402  pAreaPinMinus->Restart(out);
403  }
404 
405  if (pAreaOrifices) {
406  out
407  << ", orifice, ",
408  pAreaOrifices->Restart(out);
409  }
410 
411  /*
412  * dati parte viscosa
413  */
414  out
415  << ", "
416  << AreaFluid << ", "
417  << RhoFluid << ", "
418  << Cd;
419 
420  return out;
421  };
422 
423  virtual void
424  Update(const doublereal& Eps, const doublereal& EpsPrime = 0.) {
425  Epsilon = Eps;
426  EpsilonPrime = EpsPrime;
427 
428  FDEPrime = 0.;
429 
430  /*
431  * Parte elastica
432  */
433 
434  doublereal CurrEpsilon = Epsilon-Get();
435  doublereal VRatio = 1./(1.+Cint*CurrEpsilon);
436  doublereal Adiab = pow(VRatio, Gamma);
437 
438  dPressure = P0*Adiab;
439 
440  /* FIXME */
441  F = -A0*dPressure;
442 
443  dFelastic = F;
444 
445  if (FrictionAmpl != 0.) {
446  F *= (1.-FrictionAmpl*tanh(EpsPrime/EpsPrimeRef));
447  }
448 
449  FDE = Gamma*Cint*VRatio*F;
450 
451  bool ChangeJac(false);
452 
453  if (CurrEpsilon > EpsMax) {
454  FDE += Penalty;
455 #if 0
456  doublereal dFP = Penalty*(CurrEpsilon-EpsMax)
457  + PenaltyPrime*EpsPrime;
458  FDEPrime = PenaltyPrime;
459 #endif
460  doublereal dFP = Penalty*(CurrEpsilon-EpsMax);
461  if (EpsPrime > 0.) {
462  FDEPrime = PenaltyPrime;
463  dFP += PenaltyPrime*EpsPrime;
464  }
465 
466  dFelastic += dFP;
467  F += dFP;
468 
469  if (!bPenalty) {
470  bPenalty = true;
471  ChangeJac = true;
472  }
473 
474  } else if (CurrEpsilon < EpsMin) {
475  FDE += Penalty;
476 #if 0
477  doublereal dFP = Penalty*(CurrEpsilon-EpsMin)
478  + PenaltyPrime*EpsPrime;
479  FDEPrime = PenaltyPrime;
480 #endif
481  doublereal dFP = Penalty*(CurrEpsilon-EpsMin);
482  if (EpsPrime < 0.) {
483  FDEPrime = PenaltyPrime;
484  dFP += PenaltyPrime*EpsPrime;
485  }
486 
487  dFelastic += dFP;
488  F += dFP;
489 
490  if (!bPenalty) {
491  bPenalty = true;
492  ChangeJac = true;
493  }
494 
495  } else if (bPenalty) {
496  bPenalty = false;
497  ChangeJac = true;
498  }
499 
500 
501  /*
502  * Parte viscosa
503  *
504  * FIXME: manca L0 per scalare correttamente la velocita'
505  * (basta metterla in Cd!!!)
506  */
507  dArea = 0.;
508  if (pAreaPinPlus != NULL) {
509  if (copysign(1., EpsPrime) == 1.) {
510  dArea += pAreaPinPlus->dGet(CurrEpsilon);
511  } else {
512  dArea += pAreaPinMinus->dGet(CurrEpsilon);
513  }
514  }
515 
516  if (pAreaOrifices != NULL) {
517  dArea += pAreaOrifices->dGet(EpsPrime);
518  }
519 
520  if (dArea <= 0.) {
521  silent_cerr("ShockAbsorberConstitutiveLaw::Update:"
522  " null or negative area" << std::endl);
524  }
525 
526  doublereal d = .5*RhoFluid*AreaFluid*pow(AreaFluid/(dArea*Cd), 2);
527 
528  dFviscous = d*EpsPrime*fabs(EpsPrime);
529 
530  F += dFviscous;
531  FDEPrime += d*fabs(EpsPrime);
532 
533  if (ChangeJac) {
535  }
536  };
537 
538  /*
539  * Metodi per l'estrazione di dati "privati".
540  * Si suppone che l'estrattore li sappia interpretare.
541  * Come default non ci sono dati privati estraibili
542  */
543  virtual unsigned int iGetNumPrivData(void) const {
544  /*
545  * deve essere pari al totale di dati che
546  * si intende esportare
547  */
548  return 4;
549  };
550 
551  /*
552  * Maps a string (possibly with substrings) to a private data;
553  * returns a valid index ( > 0 && <= iGetNumPrivData()) or 0
554  * in case of unrecognized data; error must be handled by caller
555  */
556  virtual unsigned int iGetPrivDataIdx(const char *s) const {
557  ASSERT(s != NULL);
558 
559  if (strcmp(s, "p") == 0) {
560  return 1;
561  }
562 
563  if (strcmp(s, "A") == 0) {
564  return 2;
565  }
566 
567  if (strcmp(s, "Fe") == 0) {
568  return 3;
569  }
570 
571  if (strcmp(s, "Fv") == 0) {
572  return 4;
573  }
574 
575  /*
576  * aggiungere i nomi dei dati che si intende esportare
577  */
578 
579  /* error; handle later */
580  return 0;
581  };
582 
583  /*
584  * Returns the current value of a private data
585  * with 0 < i <= iGetNumPrivData()
586  */
587  virtual doublereal dGetPrivData(unsigned int i) const {
588  ASSERT(i > 0 && i <= iGetNumPrivData());
589 
590  switch (i) {
591  case 1:
592  return dPressure;
593 
594  case 2:
595  return dArea;
596 
597  case 3:
598  return dFelastic;
599 
600  case 4:
601  return dFviscous;
602 
603  /* aggiungere ulteriori case */
604  }
605 
607  };
608 
609  virtual std::ostream& OutputAppend(std::ostream& out) const {
610  return out << " " << dPressure << " " << dArea
611  << " " << dFelastic << " " << dFviscous;
612  };
613 };
614 
615 /* ShockAbsorberConstitutiveLaw - begin */
616 
617 #endif /* SHOCKABSORBER_H */
618 
GradientExpression< UnaryExpr< FuncTanh, Expr > > tanh(const GradientExpression< Expr > &u)
Definition: gradient.h:2982
virtual std::ostream & Restart(std::ostream &out) const
virtual std::ostream & Restart(std::ostream &out) const
Definition: shockabsorber.h:78
const doublereal defaultPenalty
Definition: shockabsorber.h:48
const doublereal defaultPenaltyPrime
Definition: shockabsorber.h:49
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
const doublereal defaultEpsMin
Definition: shockabsorber.h:46
std::ostream & Write(std::ostream &out, const FullMatrixHandler &m, const char *s, const char *s2)
Definition: fullmh.cc:376
#define NO_OP
Definition: myassert.h:74
GradientExpression< UnaryExpr< FuncFabs, Expr > > fabs(const GradientExpression< Expr > &u)
Definition: gradient.h:2973
virtual unsigned int iGetPrivDataIdx(const char *s) const
virtual ConstitutiveLaw< T, Tder > * pCopy(void) const
Definition: shockabsorber.h:73
TplDriveCaller< T > * pGetDriveCaller(void) const
Definition: tpldrive.h:105
virtual ~ShockAbsorberConstitutiveLaw(void)
Definition: shockabsorber.h:68
virtual void Update(const doublereal &Eps, const doublereal &EpsPrime=0.)
virtual std::ostream & OutputAppend(std::ostream &out) const
Definition: mbdyn.h:76
virtual bool IsKeyWord(const char *sKeyWord)
Definition: parser.cc:910
ShockAbsorberConstitutiveLaw(const ShockAbsorberConstitutiveLaw *p)
doublereal copysign(doublereal x, doublereal y)
Definition: gradient.h:97
#define ASSERT(expression)
Definition: colamd.c:977
virtual void Update(const T &, const T &=0.)
Definition: shockabsorber.h:85
virtual unsigned int iGetNumPrivData(void) const
#define SAFENEWWITHCONSTRUCTOR(pnt, item, constructor)
Definition: mynewmem.h:698
const doublereal defaultEpsMax
Definition: shockabsorber.h:47
Definition: except.h:79
virtual DriveCaller * pCopy(void) const =0
virtual unsigned int iGetNumPrivData(void) const
Definition: simentity.cc:136
ShockAbsorberConstitutiveLaw(const DataManager *pDM, TplDriveCaller< doublereal > *pDC, MBDynParser &HP)
virtual ConstitutiveLaw< doublereal, doublereal > * pCopy(void) const
ShockAbsorberConstitutiveLaw(const DataManager *pDM, TplDriveCaller< T > *pDC, MBDynParser &HP)
Definition: shockabsorber.h:59
virtual bool IsArg(void)
Definition: parser.cc:807
virtual doublereal dGetPrivData(unsigned int i) const
DriveCaller * GetDriveCaller(bool bDeferred=false)
Definition: mbpar.cc:2033
double doublereal
Definition: colamd.c:52
virtual HighParser::ErrOut GetLineData(void) const
Definition: parsinc.cc:697
T Get(void) const
Definition: tpldrive.h:113
virtual doublereal GetReal(const doublereal &dDefval=0.0)
Definition: parser.cc:1056