1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/drive_.h,v 1.60 2017/09/09 09:17:32 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 /* drivers */
33
34 #ifndef DRIVE__H
35 #define DRIVE__H
36
37 /* include generali */
38 #include "parser.h"
39 #include <sstream>
40 #ifdef USE_EE
41 #include <thread>
42 #endif // USE_EE
43
44 /* include per il debug */
45 #include "myassert.h"
46 #include "mynewmem.h"
47 #include "except.h"
48
49 /* include del programma */
50 #include "mathp.h"
51 #include "output.h"
52 #include "withlab.h"
53
54 #include "drive.h"
55 #include "filedrv.h"
56
57
58 /* StringDriveCaller - begin */
59
60 class StringDriveCaller : public DriveCaller {
61 private:
62 // we keep the string just in case...
63 const std::string sEvalStr;
64
65 #ifdef USE_EE
66 // "smart" shared pointer; needs -std=c++11
67
68 // TODO: actually, all drive callers could be wrapped in shared pointers
69 class SharedExpr : public std::enable_shared_from_this<SharedExpr> {
70 private:
71 const ExpressionElement *m_expr;
72 public:
SharedExpr(const ExpressionElement * expr)73 SharedExpr(const ExpressionElement *expr) : m_expr(expr) {};
~SharedExpr(void)74 ~SharedExpr(void) { delete m_expr; };
Get(void)75 const ExpressionElement *Get(void) const { return m_expr; };
pCopy(void)76 std::shared_ptr<const SharedExpr> pCopy(void) const { return shared_from_this(); };
77 };
78
79 typedef std::shared_ptr<const SharedExpr> SharedExprPtr_t;
80
81 SharedExprPtr_t m_expr;
82 #endif // USE_EE
83
84 public:
85 #ifdef USE_EE
86 StringDriveCaller(const DriveHandler* pDH, const std::string& sTmpStr, const ExpressionElement *expr);
87 StringDriveCaller(const DriveHandler* pDH, const std::string& sTmpStr, SharedExprPtr_t expr);
88 #else // ! USE_EE
89 StringDriveCaller(const DriveHandler* pDH, const std::string& sTmpStr);
90 #endif // ! USE_EE
91
92 ~StringDriveCaller(void);
93
94 /* Scrive il contributo del DriveCaller al file di restart */
95 virtual std::ostream& Restart(std::ostream& out) const;
96
97 /* Copia */
98 virtual DriveCaller* pCopy(void) const;
99
100 inline doublereal dGet(const doublereal& dVar) const;
101 inline doublereal dGet(void) const;
102 };
103
104 inline doublereal
dGet(const doublereal & dVar)105 StringDriveCaller::dGet(const doublereal& dVar) const
106 {
107 DriveCaller::pDrvHdl->SetVar(dVar);
108
109 return dGet();
110 }
111
112 inline doublereal
dGet(void)113 StringDriveCaller::dGet(void) const
114 {
115 #ifdef USE_EE
116 doublereal val;
117 try {
118 val = m_expr->Get()->Eval().GetReal();
119 } catch (MBDynErrBase& e) {
120 silent_cerr("StringDriveCaller::dGet(): " << e.what() << std::endl);
121 throw e;
122 }
123
124 return val;
125 #else // ! USE_EE
126 std::istringstream in(sEvalStr);
127 InputStream In(in);
128
129 return DriveCaller::pDrvHdl->dGet(In);
130 #endif // ! USE_EE
131 }
132
133 /* StringDriveCaller - end */
134
135
136 /* TimeDriveCaller - begin */
137
138 class TimeDriveCaller : public DriveCaller {
139 public:
140 TimeDriveCaller(const DriveHandler* pDH);
141 virtual ~TimeDriveCaller(void);
142
143 /* Scrive il contributo del DriveCaller al file di restart */
144 virtual std::ostream& Restart(std::ostream& out) const;
145
146 /* Copia */
147 virtual DriveCaller* pCopy(void) const;
148
149 inline doublereal dGet(const doublereal& dVar) const;
150 inline doublereal dGet(void) const;
151
152 /* this is about drives that are differentiable */
153 virtual bool bIsDifferentiable(void) const;
154 virtual doublereal dGetP(const doublereal& dVar) const;
155 virtual inline doublereal dGetP(void) const;
156 };
157
158 inline doublereal
dGet(const doublereal & dVar)159 TimeDriveCaller::dGet(const doublereal& dVar) const
160 {
161 return dVar;
162 }
163
164 inline doublereal
dGet(void)165 TimeDriveCaller::dGet(void) const
166 {
167 return pDrvHdl->dGetTime();
168 }
169
170 inline bool
bIsDifferentiable(void)171 TimeDriveCaller::bIsDifferentiable(void) const
172 {
173 return true;
174 }
175
176 inline doublereal
dGetP(const doublereal &)177 TimeDriveCaller::dGetP(const doublereal& /* dVar */ ) const
178 {
179 return 1.;
180 }
181
182 inline doublereal
dGetP(void)183 TimeDriveCaller::dGetP(void) const
184 {
185 return 1.;
186 }
187
188 /* TimeDriveCaller - end */
189
190 /* TimeStepDriveCaller - begin */
191
192 class TimeStepDriveCaller : public DriveCaller {
193 public:
194 TimeStepDriveCaller(const DriveHandler* pDH);
195 virtual ~TimeStepDriveCaller(void);
196
197 /* Scrive il contributo del DriveCaller al file di restart */
198 virtual std::ostream& Restart(std::ostream& out) const;
199
200 /* Copia */
201 virtual DriveCaller* pCopy(void) const;
202
203 inline doublereal dGet(const doublereal& dVar) const;
204 inline doublereal dGet(void) const;
205 };
206
207 inline doublereal
dGet(const doublereal & dVar)208 TimeStepDriveCaller::dGet(const doublereal& dVar) const
209 {
210 return dVar;
211 }
212
213 inline doublereal
dGet(void)214 TimeStepDriveCaller::dGet(void) const
215 {
216 return pDrvHdl->dGetTimeStep();
217 }
218
219 /* TimeStepDriveCaller - end */
220
221
222 /* MultDriveCaller - begin */
223
224 class MultDriveCaller : public DriveCaller {
225 protected:
226 DriveOwner DO1, DO2;
227
228 public:
229 MultDriveCaller(const DriveHandler* pDH,
230 const DriveCaller *pDC1, const DriveCaller *pDC2);
231 virtual ~MultDriveCaller(void);
232
233 /* Scrive il contributo del DriveCaller al file di restart */
234 virtual std::ostream& Restart(std::ostream& out) const;
235
236 /* Copia */
237 virtual DriveCaller* pCopy(void) const;
238
239 inline doublereal dGet(void) const;
240 inline doublereal dGet(const doublereal& dVar) const;
241
242 /* this is about drives that are differentiable */
243 virtual bool bIsDifferentiable(void) const;
244 virtual doublereal dGetP(const doublereal& dVar) const;
245 };
246
247 inline doublereal
dGet(void)248 MultDriveCaller::dGet(void) const
249 {
250 return DO1.pGetDriveCaller()->dGet()*DO2.pGetDriveCaller()->dGet();
251 }
252
253 inline doublereal
dGet(const doublereal & dVar)254 MultDriveCaller::dGet(const doublereal& dVar) const
255 {
256 return DO1.pGetDriveCaller()->dGet(dVar)*DO2.pGetDriveCaller()->dGet(dVar);
257 }
258
259 inline bool
bIsDifferentiable(void)260 MultDriveCaller::bIsDifferentiable(void) const
261 {
262 return DO1.pGetDriveCaller()->bIsDifferentiable()
263 && DO2.pGetDriveCaller()->bIsDifferentiable();
264 }
265
266 inline doublereal
dGetP(const doublereal & dVar)267 MultDriveCaller::dGetP(const doublereal& dVar) const
268 {
269 return DO1.pGetDriveCaller()->dGetP(dVar)*DO2.pGetDriveCaller()->dGet(dVar)
270 + DO1.pGetDriveCaller()->dGet(dVar)*DO2.pGetDriveCaller()->dGetP(dVar);
271 }
272
273 /* MultDriveCaller - end */
274
275 /* LinearDriveCaller - begin */
276
277 class LinearDriveCaller : public DriveCaller {
278 private:
279 doublereal dC0;
280 doublereal dC1;
281
282 public:
283 LinearDriveCaller(const DriveHandler* pDH, doublereal d0, doublereal d1);
284 virtual ~LinearDriveCaller(void);
285
286 /* Copia */
287 virtual DriveCaller* pCopy(void) const;
288
289 /* Scrive il contributo del DriveCaller al file di restart */
290 virtual std::ostream& Restart(std::ostream& out) const;
291
292 inline doublereal dGet(const doublereal& dVar) const;
293 #if 0
294 inline doublereal dGet(void) const;
295 #endif
296
297 /* this is about drives that are differentiable */
298 virtual bool bIsDifferentiable(void) const;
299 virtual doublereal dGetP(const doublereal& dVar) const;
300 #if 0
301 virtual inline doublereal dGetP(void) const;
302 #endif
303 };
304
305 inline doublereal
dGet(const doublereal & dVar)306 LinearDriveCaller::dGet(const doublereal& dVar) const
307 {
308 return dC0 + dVar*dC1;
309 }
310
311 inline bool
bIsDifferentiable(void)312 LinearDriveCaller::bIsDifferentiable(void) const
313 {
314 return true;
315 }
316
317 inline doublereal
dGetP(const doublereal &)318 LinearDriveCaller::dGetP(const doublereal& /* dVar */ ) const
319 {
320 return dC1;
321 }
322
323 /* LinearDriveCaller - end */
324
325
326 /* ParabolicDriveCaller - begin */
327
328 class ParabolicDriveCaller : public DriveCaller {
329 private:
330 doublereal dC0;
331 doublereal dC1;
332 doublereal dC2;
333
334 public:
335 ParabolicDriveCaller(const DriveHandler* pDH,
336 doublereal d0, doublereal d1, doublereal d2);
337 virtual ~ParabolicDriveCaller(void);
338
339 /* Copia */
340 virtual DriveCaller* pCopy(void) const;
341
342 /* Scrive il contributo del DriveCaller al file di restart */
343 virtual std::ostream& Restart(std::ostream& out) const;
344
345 inline doublereal dGet(const doublereal& dVar) const;
346 #if 0
347 inline doublereal dGet(void) const;
348 #endif
349
350 /* this is about drives that are differentiable */
351 virtual bool bIsDifferentiable(void) const;
352 virtual doublereal dGetP(const doublereal& dVar) const;
353 #if 0
354 virtual inline doublereal dGetP(void) const;
355 #endif
356 };
357
358 inline doublereal
dGet(const doublereal & dVar)359 ParabolicDriveCaller::dGet(const doublereal& dVar) const
360 {
361 return dC0 + dVar*(dC1 + dVar*dC2);
362 }
363
364 inline bool
bIsDifferentiable(void)365 ParabolicDriveCaller::bIsDifferentiable(void) const
366 {
367 return true;
368 }
369
370 inline doublereal
dGetP(const doublereal & dVar)371 ParabolicDriveCaller::dGetP(const doublereal& dVar) const
372 {
373 return dC1 + dVar*2*dC2;
374 }
375
376 /* ParabolicDriveCaller - end */
377
378
379 /* CubicDriveCaller - begin */
380
381 class CubicDriveCaller : public DriveCaller {
382 private:
383 doublereal dC0;
384 doublereal dC1;
385 doublereal dC2;
386 doublereal dC3;
387
388 public:
389 CubicDriveCaller(const DriveHandler* pDH,
390 doublereal d0, doublereal d1,
391 doublereal d2, doublereal d3);
392 virtual ~CubicDriveCaller(void);
393
394 /* Copia */
395 virtual DriveCaller* pCopy(void) const;
396
397 /* Scrive il contributo del DriveCaller al file di restart */
398 virtual std::ostream& Restart(std::ostream& out) const;
399
400 inline doublereal dGet(const doublereal& dVar) const;
401 #if 0
402 inline doublereal dGet(void) const;
403 #endif
404
405 /* this is about drives that are differentiable */
406 virtual bool bIsDifferentiable(void) const;
407 virtual doublereal dGetP(const doublereal& dVar) const;
408 #if 0
409 virtual inline doublereal dGetP(void) const;
410 #endif
411 };
412
413 inline doublereal
dGet(const doublereal & dVar)414 CubicDriveCaller::dGet(const doublereal& dVar) const
415 {
416 return dC0 + dVar*(dC1 + dVar*(dC2 + dVar*dC3));
417 }
418
419 inline bool
bIsDifferentiable(void)420 CubicDriveCaller::bIsDifferentiable(void) const
421 {
422 return true;
423 }
424
425 inline doublereal
dGetP(const doublereal & dVar)426 CubicDriveCaller::dGetP(const doublereal& dVar) const
427 {
428 return dC1 + dVar*(2*dC2 + dVar*3*dC3);
429 }
430
431 /* CubicDriveCaller - end */
432
433
434 /* StepDriveCaller - begin */
435
436 class StepDriveCaller : public DriveCaller {
437 private:
438 doublereal dStepTime;
439 doublereal dStepValue;
440 doublereal dInitialValue;
441
442 public:
443 StepDriveCaller(const DriveHandler* pDH,
444 doublereal d1, doublereal d2, doublereal d3);
445 ~StepDriveCaller(void);
446
447 /* Copia */
448 virtual DriveCaller* pCopy(void) const;
449
450 /* Scrive il contributo del DriveCaller al file di restart */
451 virtual std::ostream& Restart(std::ostream& out) const;
452
453 inline doublereal dGet(const doublereal& dVar) const;
454 #if 0
455 inline doublereal dGet(void) const;
456 #endif
457
458 /* this is about drives that are differentiable */
459 virtual bool bIsDifferentiable(void) const;
460 virtual doublereal dGetP(const doublereal& dVar) const;
461 #if 0
462 virtual inline doublereal dGetP(void) const;
463 #endif
464 };
465
466 inline doublereal
dGet(const doublereal & dVar)467 StepDriveCaller::dGet(const doublereal& dVar) const
468 {
469 if (dVar > dStepTime) {
470 return dStepValue;
471 }
472
473 if (dVar < dStepTime) {
474 return dInitialValue;
475 }
476
477 /* else if dVar == dStepTime */
478 return (dInitialValue + dStepValue)/2.;
479 }
480
481 inline bool
bIsDifferentiable(void)482 StepDriveCaller::bIsDifferentiable(void) const
483 {
484 return true;
485 }
486
487 inline doublereal
dGetP(const doublereal & dVar)488 StepDriveCaller::dGetP(const doublereal& dVar) const
489 {
490 /* FIXME: what if we get exactly to the step time? */
491 if (dVar == dStepTime) {
492 silent_cerr("singularity in step drive derivative at " << dVar << std::endl);
493 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
494 }
495
496 return 0.;
497 }
498
499 /* StepDriveCaller - end */
500
501
502 /* DoubleStepDriveCaller - begin */
503
504 class DoubleStepDriveCaller : public DriveCaller {
505 private:
506 doublereal dStepTime;
507 doublereal dStepValue;
508 doublereal dEndStepTime;
509 doublereal dInitialValue;
510
511 public:
512 DoubleStepDriveCaller(const DriveHandler* pDH,
513 doublereal d1, doublereal d2,
514 doublereal d3, doublereal d4);
515 ~DoubleStepDriveCaller(void);
516
517 /* Copia */
518 virtual DriveCaller* pCopy(void) const;
519
520 /* Scrive il contributo del DriveCaller al file di restart */
521 virtual std::ostream& Restart(std::ostream& out) const;
522
523 inline doublereal dGet(const doublereal& dVar) const;
524 #if 0
525 inline doublereal dGet(void) const;
526 #endif
527
528 /* this is about drives that are differentiable */
529 virtual bool bIsDifferentiable(void) const;
530 virtual doublereal dGetP(const doublereal& dVar) const;
531 #if 0
532 virtual inline doublereal dGetP(void) const;
533 #endif
534 };
535
536 inline doublereal
dGet(const doublereal & dVar)537 DoubleStepDriveCaller::dGet(const doublereal& dVar) const
538 {
539 if (dVar > dStepTime && dVar < dEndStepTime) {
540 return dStepValue;
541 }
542
543 if (dVar < dStepTime || dVar > dEndStepTime) {
544 return dInitialValue;
545 }
546
547 /* else if dVar == dStepTime || dVar == dEndStepTime */
548 return (dInitialValue + dStepValue)/2.;
549 }
550
551 inline bool
bIsDifferentiable(void)552 DoubleStepDriveCaller::bIsDifferentiable(void) const
553 {
554 return true;
555 }
556
557 inline doublereal
dGetP(const doublereal & dVar)558 DoubleStepDriveCaller::dGetP(const doublereal& dVar) const
559 {
560 /* FIXME: what if we get exactly to the step time? */
561 if (dVar == dStepTime || dVar == dEndStepTime) {
562 silent_cerr("singularity in double step drive derivative at " << dVar << std::endl);
563 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
564 }
565
566 return 0.;
567 }
568
569 /* DoubleStepDriveCaller - end */
570
571
572 /* RampDriveCaller - begin */
573
574 class RampDriveCaller : public DriveCaller {
575 private:
576 doublereal dSlope;
577 doublereal dStartTime;
578 doublereal dEndTime;
579 doublereal dInitialValue;
580
581 public:
582 RampDriveCaller(const DriveHandler* pDH,
583 doublereal d1, doublereal d2, doublereal d3, doublereal d4);
584 ~RampDriveCaller(void);
585
586 /* Copia */
587 virtual DriveCaller* pCopy(void) const;
588
589 /* Scrive il contributo del DriveCaller al file di restart */
590 virtual std::ostream& Restart(std::ostream& out) const;
591
592 inline doublereal dGet(const doublereal& dVar) const;
593 #if 0
594 inline doublereal dGet(void) const;
595 #endif
596
597 /* this is about drives that are differentiable */
598 virtual bool bIsDifferentiable(void) const;
599 virtual doublereal dGetP(const doublereal& dVar) const;
600 #if 0
601 virtual inline doublereal dGetP(void) const;
602 #endif
603 };
604
605 inline doublereal
dGet(const doublereal & dVar)606 RampDriveCaller::dGet(const doublereal& dVar) const
607 {
608 doublereal dVal;
609
610 dVal = dInitialValue;
611 if (dVar > dStartTime) {
612 doublereal dEnd;
613
614 if (dVar > dEndTime) {
615 dEnd = dEndTime;
616
617 } else {
618 dEnd = dVar;
619 }
620
621 dVal += dSlope*(dEnd - dStartTime);
622 }
623
624 return dVal;
625 }
626
627 inline bool
bIsDifferentiable(void)628 RampDriveCaller::bIsDifferentiable(void) const
629 {
630 return true;
631 }
632
633 inline doublereal
dGetP(const doublereal & dVar)634 RampDriveCaller::dGetP(const doublereal& dVar) const
635 {
636 if (dVar < dStartTime || dVar > dEndTime) {
637 return 0.;
638 }
639
640 if (dVar == dStartTime || dVar == dEndTime) {
641 return dSlope/2.;
642 }
643
644 return dSlope;
645 }
646
647 /* RampDriveCaller - end */
648
649
650 /* DoubleRampDriveCaller - begin */
651
652 /* note: can be obtained with an array of two ramps */
653
654 class DoubleRampDriveCaller : public DriveCaller {
655 private:
656 doublereal dAscendingSlope;
657 doublereal dAscendingStartTime;
658 doublereal dAscendingEndTime;
659 doublereal dDescendingSlope;
660 doublereal dDescendingStartTime;
661 doublereal dDescendingEndTime;
662 doublereal dInitialValue;
663
664 public:
665 DoubleRampDriveCaller(const DriveHandler* pDH,
666 doublereal d1, doublereal d2, doublereal d3,
667 doublereal d4, doublereal d5, doublereal d6,
668 doublereal d7);
669 ~DoubleRampDriveCaller(void);
670
671 /* Copia */
672 virtual DriveCaller* pCopy(void) const;
673
674 /* Scrive il contributo del DriveCaller al file di restart */
675 virtual std::ostream& Restart(std::ostream& out) const;
676
677 inline doublereal dGet(const doublereal& dVar) const;
678 #if 0
679 inline doublereal dGet(void) const;
680 #endif
681
682 /* this is about drives that are differentiable */
683 virtual bool bIsDifferentiable(void) const;
684 virtual doublereal dGetP(const doublereal& dVar) const;
685 #if 0
686 virtual inline doublereal dGetP(void) const;
687 #endif
688 };
689
690 inline doublereal
dGet(const doublereal & dVar)691 DoubleRampDriveCaller::dGet(const doublereal& dVar) const
692 {
693 doublereal dVal;
694
695 dVal = dInitialValue;
696 if (dVar > dAscendingStartTime) {
697 doublereal dEnd;
698
699 if (dVar > dAscendingEndTime) {
700 dEnd = dAscendingEndTime;
701
702 } else {
703 dEnd = dVar;
704 }
705
706 dVal += dAscendingSlope*(dEnd - dAscendingStartTime);
707
708 if (dVar > dDescendingStartTime) {
709 if (dVar > dDescendingEndTime) {
710 dEnd = dDescendingEndTime;
711
712 } else {
713 dEnd = dVar;
714 }
715
716 dVal += dDescendingSlope*(dEnd - dDescendingStartTime);
717 }
718 }
719
720 return dVal;
721 }
722
723 inline bool
bIsDifferentiable(void)724 DoubleRampDriveCaller::bIsDifferentiable(void) const
725 {
726 return true;
727 }
728
729 inline doublereal
dGetP(const doublereal & dVar)730 DoubleRampDriveCaller::dGetP(const doublereal& dVar) const
731 {
732 if (dVar < dAscendingStartTime || dVar > dDescendingEndTime
733 || (dVar > dAscendingEndTime && dVar < dDescendingStartTime))
734 {
735 return 0.;
736 }
737
738 if (dVar == dAscendingStartTime || dVar == dAscendingEndTime) {
739 return dAscendingSlope/2.;
740 }
741
742 if (dVar == dDescendingStartTime || dVar == dDescendingEndTime) {
743 return dDescendingSlope/2.;
744 }
745
746 if (dVar < dAscendingEndTime) {
747 return dAscendingSlope;
748 }
749
750 return dDescendingSlope;
751 }
752
753 /* DoubleRampDriveCaller - end */
754
755
756 /* SineDriveCaller - begin */
757
758 class SineDriveCaller : public DriveCaller {
759 private:
760 doublereal dStartTime;
761 doublereal dOmega;
762 doublereal dAmplitude;
763 integer iNumCycles;
764 doublereal dInitialValue;
765 doublereal dEndTime;
766 doublereal dFinalValue;
767 bool bNeverEnd;
768
769 public:
770 SineDriveCaller(const DriveHandler* pDH,
771 doublereal d1, doublereal d2, doublereal d3,
772 integer iNumCyc, doublereal d4);
773 ~SineDriveCaller(void);
774
775 /* Copia */
776 virtual DriveCaller* pCopy(void) const;
777
778 /* Scrive il contributo del DriveCaller al file di restart */
779 virtual std::ostream& Restart(std::ostream& out) const;
780
781 inline doublereal dGet(const doublereal& dVar) const;
782 #if 0
783 inline doublereal dGet(void) const;
784 #endif
785
786 /* this is about drives that are differentiable */
787 virtual bool bIsDifferentiable(void) const;
788 virtual doublereal dGetP(const doublereal& dVar) const;
789 #if 0
790 virtual inline doublereal dGetP(void) const;
791 #endif
792 };
793
794 inline doublereal
dGet(const doublereal & dVar)795 SineDriveCaller::dGet(const doublereal& dVar) const
796 {
797 if (dVar <= dStartTime) {
798 return dInitialValue;
799 }
800
801 if (bNeverEnd || dVar < dEndTime) {
802 return dInitialValue + dAmplitude*sin(dOmega*(dVar - dStartTime));
803 }
804
805 /* else if dVar > dEndTime */
806 return dFinalValue;
807 }
808
809 inline bool
bIsDifferentiable(void)810 SineDriveCaller::bIsDifferentiable(void) const
811 {
812 return true;
813 }
814
815 inline doublereal
dGetP(const doublereal & dVar)816 SineDriveCaller::dGetP(const doublereal& dVar) const
817 {
818 if (dVar < dStartTime) {
819 return 0.;
820 }
821
822 if (!bNeverEnd && dVar > dEndTime) {
823 return 0.;
824 }
825
826 doublereal dVal = dAmplitude*dOmega*cos(dOmega*(dVar - dStartTime));
827
828 if (dVar == dStartTime || (!bNeverEnd && dVar == dEndTime)) {
829 dVal /= 2.;
830 }
831
832 return dVal;
833 }
834
835 /* SineDriveCaller - end */
836
837
838 /* CosineDriveCaller - begin */
839
840 class CosineDriveCaller : public DriveCaller {
841 private:
842 doublereal dStartTime;
843 doublereal dOmega;
844 doublereal dAmplitude;
845 integer iNumCycles;
846 doublereal dInitialValue;
847 doublereal dEndTime;
848 doublereal dFinalValue;
849 bool bNeverEnd;
850
851 public:
852 CosineDriveCaller(const DriveHandler* pDH,
853 doublereal d1, doublereal d2, doublereal d3,
854 integer iNumCyc, doublereal d4);
855 ~CosineDriveCaller(void);
856
857 /* Copia */
858 virtual DriveCaller* pCopy(void) const;
859
860 /* Scrive il contributo del DriveCaller al file di restart */
861 virtual std::ostream& Restart(std::ostream& out) const;
862
863 inline doublereal dGet(const doublereal& dVar) const;
864 #if 0
865 inline doublereal dGet(void) const;
866 #endif
867
868 /* this is about drives that are differentiable */
869 virtual bool bIsDifferentiable(void) const;
870 virtual doublereal dGetP(const doublereal& dVar) const;
871 #if 0
872 virtual inline doublereal dGetP(void) const;
873 #endif
874 };
875
876 inline doublereal
dGet(const doublereal & dVar)877 CosineDriveCaller::dGet(const doublereal& dVar) const
878 {
879 if (dVar < dStartTime) {
880 return dInitialValue;
881 }
882
883 if (bNeverEnd || dVar < dEndTime) {
884 return dInitialValue + dAmplitude*(1. - cos(dOmega*(dVar - dStartTime)));
885 }
886
887 /* else if dTime > dEndTime */
888 return dFinalValue;
889 }
890
891 inline bool
bIsDifferentiable(void)892 CosineDriveCaller::bIsDifferentiable(void) const
893 {
894 return true;
895 }
896
897 inline doublereal
dGetP(const doublereal & dVar)898 CosineDriveCaller::dGetP(const doublereal& dVar) const
899 {
900 if (dVar < dStartTime) {
901 return 0.;
902 }
903
904 if (!bNeverEnd && dVar > dEndTime) {
905 return 0.;
906 }
907
908 return dAmplitude*dOmega*sin(dOmega*(dVar - dStartTime));
909 }
910
911 /* CosineDriveCaller - end */
912
913
914 /* TanhDriveCaller - begin */
915
916 class TanhDriveCaller : public DriveCaller {
917 private:
918 doublereal dStart;
919 doublereal dA;
920 doublereal dB;
921 doublereal dInitialValue;
922
923 public:
924 TanhDriveCaller(const DriveHandler* pDH,
925 doublereal ds, doublereal da, doublereal db, doublereal di);
926 ~TanhDriveCaller(void);
927
928 /* Copia */
929 virtual DriveCaller* pCopy(void) const;
930
931 /* Scrive il contributo del DriveCaller al file di restart */
932 virtual std::ostream& Restart(std::ostream& out) const;
933
934 inline doublereal dGet(const doublereal& dVar) const;
935
936 /* this is about drives that are differentiable */
937 virtual bool bIsDifferentiable(void) const;
938 virtual doublereal dGetP(const doublereal& dVar) const;
939 };
940
941 inline doublereal
dGet(const doublereal & dVar)942 TanhDriveCaller::dGet(const doublereal& dVar) const
943 {
944 return dInitialValue + dA*std::tanh(dB*(dVar - dStart));
945 }
946
947 inline bool
bIsDifferentiable(void)948 TanhDriveCaller::bIsDifferentiable(void) const
949 {
950 return true;
951 }
952
953 inline doublereal
dGetP(const doublereal & dVar)954 TanhDriveCaller::dGetP(const doublereal& dVar) const
955 {
956 return dA*dB*(1. - std::tanh(dB*(dVar - dStart)));
957 }
958
959 /* TanhDriveCaller - end */
960
961
962 /* FourierSeriesDriveCaller - begin */
963
964 class FourierSeriesDriveCaller : public DriveCaller {
965 private:
966 doublereal dStartTime;
967 doublereal dOmega;
968 mutable std::vector<doublereal> amplitudes;
969 integer iNumCycles;
970 doublereal dInitialValue;
971 doublereal dEndTime;
972 bool bNeverEnd;
973
974 public:
975 FourierSeriesDriveCaller(const DriveHandler* pDH,
976 doublereal dStartTime,
977 doublereal dOmega,
978 std::vector<doublereal>& a,
979 integer iNumCyc,
980 doublereal dInitialValue);
981 ~FourierSeriesDriveCaller(void);
982
983 /* Copia */
984 virtual DriveCaller* pCopy(void) const;
985
986 /* Scrive il contributo del DriveCaller al file di restart */
987 virtual std::ostream& Restart(std::ostream& out) const;
988
989 inline doublereal dGet(const doublereal& dVar) const;
990 #if 0
991 inline doublereal dGet(void) const;
992 #endif
993
994 /* this is about drives that are differentiable */
995 virtual bool bIsDifferentiable(void) const;
996 virtual doublereal dGetP(const doublereal& dVar) const;
997 #if 0
998 virtual inline doublereal dGetP(void) const;
999 #endif
1000 };
1001
1002 inline doublereal
dGet(const doublereal & dVar)1003 FourierSeriesDriveCaller::dGet(const doublereal& dVar) const
1004 {
1005 doublereal d = dInitialValue;
1006
1007 if (dVar >= dStartTime && (bNeverEnd || dVar < dEndTime)) {
1008 doublereal t = dVar - dStartTime;
1009
1010 d += amplitudes[0];
1011
1012 for (unsigned i = 2; i < amplitudes.size(); i += 2 ) {
1013 doublereal theta = (i/2)*dOmega*t;
1014
1015 d += amplitudes[i - 1]*cos(theta) + amplitudes[i]*sin(theta);
1016 }
1017 }
1018
1019 return d;
1020 }
1021
1022 inline bool
bIsDifferentiable(void)1023 FourierSeriesDriveCaller::bIsDifferentiable(void) const
1024 {
1025 return true;
1026 }
1027
1028 inline doublereal
dGetP(const doublereal & dVar)1029 FourierSeriesDriveCaller::dGetP(const doublereal& dVar) const
1030 {
1031 if (dVar < dStartTime) {
1032 return 0.;
1033 }
1034
1035 if (!bNeverEnd && dVar > dEndTime) {
1036 return 0.;
1037 }
1038
1039 doublereal t = dVar - dStartTime;
1040 doublereal dVal = 0.;
1041 bool bSingular = (amplitudes[0] != 0);
1042 for (unsigned i = 2; i < amplitudes.size(); i += 2 ) {
1043 doublereal omega = (i/2)*dOmega;
1044 doublereal theta = omega*t;
1045
1046 dVal += omega*(-amplitudes[i - 1]*sin(theta) + amplitudes[i]*cos(theta));
1047
1048 if (amplitudes[i - 1] != 0) {
1049 bSingular = true;
1050 }
1051 }
1052
1053 if (dVar == dStartTime || (!bNeverEnd && dVar == dEndTime)) {
1054 if (bSingular) {
1055 silent_cerr("singularity in fourier series drive derivative at " << dVar << std::endl);
1056 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
1057 }
1058 dVal /= 2.;
1059 }
1060
1061 return dVal;
1062 }
1063
1064 /* FourierSeriesDriveCaller - end */
1065
1066
1067 /* FreqSweepDriveCaller - begin */
1068
1069 class FreqSweepDriveCaller : public DriveCaller {
1070 private:
1071 doublereal dStartTime;
1072 const DriveCaller *pOmega;
1073 const DriveCaller *pAmplitude;
1074 doublereal dInitialValue;
1075 doublereal dEndTime;
1076 doublereal dFinalValue;
1077 bool bNeverEnd;
1078
1079 public:
1080 FreqSweepDriveCaller(const DriveHandler* pDH,
1081 doublereal d1,
1082 const DriveCaller* pOmega,
1083 const DriveCaller* pAmplitude,
1084 doublereal d2,
1085 doublereal d3,
1086 doublereal d4);
1087 ~FreqSweepDriveCaller(void);
1088
1089 /* Copia */
1090 virtual DriveCaller* pCopy(void) const;
1091
1092 /* Scrive il contributo del DriveCaller al file di restart */
1093 virtual std::ostream& Restart(std::ostream& out) const;
1094
1095 inline doublereal dGet(const doublereal& dVar) const;
1096 #if 0
1097 inline doublereal dGet(void) const;
1098 #endif
1099
1100 /* this is about drives that are differentiable */
1101 virtual bool bIsDifferentiable(void) const;
1102 virtual doublereal dGetP(const doublereal& dVar) const;
1103 #if 0
1104 virtual inline doublereal dGetP(void) const;
1105 #endif
1106 };
1107
1108 inline doublereal
dGet(const doublereal & dVar)1109 FreqSweepDriveCaller::dGet(const doublereal& dVar) const
1110 {
1111 if (dVar <= dStartTime) {
1112 return dInitialValue;
1113 }
1114
1115 if (bNeverEnd || dVar < dEndTime) {
1116 return dInitialValue + pAmplitude->dGet(dVar)*sin(pOmega->dGet(dVar)*(dVar - dStartTime));
1117 }
1118
1119 /* else if dVar > dEndTime */
1120 return dFinalValue;
1121 }
1122
1123 inline bool
bIsDifferentiable(void)1124 FreqSweepDriveCaller::bIsDifferentiable(void) const
1125 {
1126 return pAmplitude->bIsDifferentiable() && pOmega->bIsDifferentiable();
1127 }
1128
1129 inline doublereal
dGetP(const doublereal & dVar)1130 FreqSweepDriveCaller::dGetP(const doublereal& dVar) const
1131 {
1132 if (dVar < dStartTime || (!bNeverEnd && dVar > dEndTime)) {
1133 return 0.;
1134 }
1135
1136 doublereal A = pAmplitude->dGet(dVar);
1137 doublereal w = pOmega->dGet(dVar);
1138 doublereal AP = pAmplitude->dGetP(dVar);
1139 doublereal wP = pOmega->dGetP(dVar);
1140 doublereal t = dVar - dStartTime;
1141
1142 doublereal dVal = AP*sin(w*t) + A*cos(w*t)*(wP*t + w);
1143 if (dVar == dStartTime || (!bNeverEnd && dVar == dEndTime)) {
1144 dVal /= 2.;
1145 }
1146
1147 return dVal;
1148 }
1149
1150 /* FreqSweepDriveCaller - end */
1151
1152
1153 /* ExpDriveCaller - begin */
1154
1155 class ExpDriveCaller : public DriveCaller {
1156 private:
1157 doublereal dAmplitude;
1158 doublereal dTimeConst;
1159 doublereal dStartTime;
1160 doublereal dInitialValue;
1161
1162 public:
1163 ExpDriveCaller(const DriveHandler* pDH,
1164 doublereal dA, doublereal dT,
1165 doublereal dS, doublereal dI);
1166 virtual ~ExpDriveCaller(void);
1167
1168 /* Copia */
1169 virtual DriveCaller* pCopy(void) const;
1170
1171 /* Scrive il contributo del DriveCaller al file di restart */
1172 virtual std::ostream& Restart(std::ostream& out) const;
1173
1174 inline doublereal dGet(const doublereal& dVar) const;
1175 #if 0
1176 inline doublereal dGet(void) const;
1177 #endif
1178
1179 /* this is about drives that are differentiable */
1180 virtual bool bIsDifferentiable(void) const;
1181 virtual doublereal dGetP(const doublereal& dVar) const;
1182 #if 0
1183 virtual inline doublereal dGetP(void) const;
1184 #endif
1185 };
1186
1187 inline doublereal
dGet(const doublereal & dVar)1188 ExpDriveCaller::dGet(const doublereal& dVar) const
1189 {
1190 if (dVar <= dStartTime) {
1191 return dInitialValue;
1192 }
1193
1194 return dInitialValue
1195 + dAmplitude*(1. - exp((dStartTime - dVar)/dTimeConst));
1196 }
1197
1198 inline bool
bIsDifferentiable(void)1199 ExpDriveCaller::bIsDifferentiable(void) const
1200 {
1201 return true;
1202 }
1203
1204 inline doublereal
dGetP(const doublereal & dVar)1205 ExpDriveCaller::dGetP(const doublereal& dVar) const
1206 {
1207 if (dVar < dStartTime) {
1208 return 0.;
1209 }
1210
1211 doublereal dVal = -dAmplitude/dTimeConst*exp((dStartTime - dVar)/dTimeConst);
1212 if (dVal == dStartTime) {
1213 dVal /= 2.;
1214 }
1215
1216 return dVal;
1217 }
1218
1219 /* ExpDriveCaller - end */
1220
1221
1222 /* RandDriveCaller - begin */
1223
1224 class RandDriveCaller : public DriveCaller {
1225 private:
1226 long int iBase;
1227 doublereal dAmplitude;
1228 doublereal dRefVal;
1229 doublereal dStartTime;
1230 doublereal dEndTime;
1231 integer iSteps;
1232 integer iRandDriveNumber;
1233
1234 public:
1235 RandDriveCaller(const DriveHandler* pDH,
1236 doublereal dA, doublereal dR,
1237 doublereal dS, doublereal dE, integer iS);
1238 virtual ~RandDriveCaller(void);
1239
1240 /* Copia */
1241 virtual DriveCaller* pCopy(void) const;
1242
1243 /* Scrive il contributo del DriveCaller al file di restart */
1244 virtual std::ostream& Restart(std::ostream& out) const;
1245
1246 inline doublereal dGet(const doublereal& dVar) const;
1247 #if 0
1248 inline doublereal dGet(void) const;
1249 #endif
1250 };
1251
1252 inline doublereal
dGet(const doublereal & dVar)1253 RandDriveCaller::dGet(const doublereal& dVar) const
1254 {
1255 if (dVar < dStartTime || dVar > dEndTime) {
1256 return dRefVal;
1257 }
1258
1259 doublereal dRand = doublereal((((unsigned long)pDrvHdl->iGetRand(iRandDriveNumber)) + iBase)%RAND_MAX);
1260 return dRefVal + dAmplitude*(2.*dRand/doublereal(RAND_MAX) - 1.);
1261 }
1262
1263 /* RandDriveCaller - end */
1264
1265
1266 /* MeterDriveCaller - begin */
1267
1268 class MeterDriveCaller : public DriveCaller {
1269 private:
1270 doublereal dStartTime;
1271 doublereal dEndTime;
1272 integer iSteps;
1273 integer iMeterDriveNumber;
1274
1275 public:
1276 MeterDriveCaller(const DriveHandler* pDH,
1277 doublereal dS, doublereal dE, integer iS);
1278 virtual ~MeterDriveCaller(void);
1279
1280 /* Copia */
1281 virtual DriveCaller* pCopy(void) const;
1282
1283 /* Scrive il contributo del DriveCaller al file di restart */
1284 virtual std::ostream& Restart(std::ostream& out) const;
1285
1286 inline doublereal dGet(const doublereal& dVar) const;
1287 #if 0
1288 inline doublereal dGet(void) const;
1289 #endif
1290
1291 inline integer iGetSteps(void) const;
1292 };
1293
1294 inline doublereal
dGet(const doublereal & dVar)1295 MeterDriveCaller::dGet(const doublereal& dVar) const
1296 {
1297 if (dVar < dStartTime || dVar > dEndTime) {
1298 return 0.;
1299 }
1300
1301 return doublereal(pDrvHdl->bGetMeter(iMeterDriveNumber));
1302 }
1303
1304 inline integer
iGetSteps(void)1305 MeterDriveCaller::iGetSteps(void) const
1306 {
1307 return iSteps;
1308 }
1309
1310 /* MeterDriveCaller - end */
1311
1312
1313 /* ClosestNextDriveCaller - begin */
1314
1315 class ClosestNextDriveCaller : public DriveCaller {
1316 private:
1317 doublereal dStartTime;
1318 doublereal dEndTime;
1319 const DriveCaller *pIncrement;
1320 integer iDriveNumber;
1321
1322 public:
1323 ClosestNextDriveCaller(const DriveHandler* pDH,
1324 doublereal dS, doublereal dE,
1325 const DriveCaller *pIncrement);
1326 virtual ~ClosestNextDriveCaller(void);
1327
1328 /* Copia */
1329 virtual DriveCaller* pCopy(void) const;
1330
1331 /* Scrive il contributo del DriveCaller al file di restart */
1332 virtual std::ostream& Restart(std::ostream& out) const;
1333
1334 inline doublereal dGet(const doublereal& dVar) const;
1335 };
1336
1337 inline doublereal
dGet(const doublereal & dVar)1338 ClosestNextDriveCaller::dGet(const doublereal& dVar) const
1339 {
1340 if (dVar < dStartTime || dVar > dEndTime) {
1341 return 0.;
1342 }
1343
1344 return doublereal(pDrvHdl->bGetClosestNext(iDriveNumber));
1345 }
1346
1347 /* ClosestNextDriveCaller - end */
1348
1349
1350 /* DirectDriveCaller - begin */
1351
1352 class DirectDriveCaller : public DriveCaller {
1353 public:
1354 DirectDriveCaller(const DriveHandler* pDH);
1355 virtual ~DirectDriveCaller(void);
1356
1357 /* Copia */
1358 virtual DriveCaller* pCopy(void) const;
1359
1360 /* Scrive il contributo del DriveCaller al file di restart */
1361 virtual std::ostream& Restart(std::ostream& out) const;
1362
1363 inline doublereal dGet(const doublereal& dVar) const;
1364 #if 0
1365 inline doublereal dGet(void) const;
1366 #endif
1367
1368 /* this is about drives that are differentiable */
1369 virtual bool bIsDifferentiable(void) const;
1370 virtual doublereal dGetP(const doublereal& dVar) const;
1371 };
1372
1373 inline doublereal
dGet(const doublereal & dVar)1374 DirectDriveCaller::dGet(const doublereal& dVar) const
1375 {
1376 return dVar;
1377 }
1378
1379 inline bool
bIsDifferentiable(void)1380 DirectDriveCaller::bIsDifferentiable(void) const
1381 {
1382 return true;
1383 }
1384
1385 inline doublereal
dGetP(const doublereal & dVar)1386 DirectDriveCaller::dGetP(const doublereal& dVar) const
1387 {
1388 return 1.;
1389 }
1390
1391 /* DirectDriveCaller - end */
1392
1393
1394 /* PiecewiseLinearDriveCaller - begin */
1395
1396 class PiecewiseLinearDriveCaller : public DriveCaller {
1397 private:
1398 unsigned int iNumPoints;
1399 doublereal *pPoints;
1400 doublereal *pVals;
1401
1402 public:
1403 PiecewiseLinearDriveCaller(const DriveHandler* pDH,
1404 unsigned int i, doublereal *p);
1405 virtual ~PiecewiseLinearDriveCaller(void);
1406
1407 /* Copia */
1408 virtual DriveCaller* pCopy(void) const;
1409
1410 /* Scrive il contributo del DriveCaller al file di restart */
1411 virtual std::ostream& Restart(std::ostream& out) const;
1412
1413 inline doublereal dGet(const doublereal& dVar) const;
1414
1415 /* this is about drives that are differentiable */
1416 virtual bool bIsDifferentiable(void) const;
1417 virtual doublereal dGetP(const doublereal& dVar) const;
1418 #if 0
1419 virtual inline doublereal dGetP(void) const;
1420 #endif
1421 };
1422
1423 inline doublereal
dGet(const doublereal & dVar)1424 PiecewiseLinearDriveCaller::dGet(const doublereal& dVar) const
1425 {
1426 if (dVar <= pPoints[0]) {
1427 return pVals[0];
1428 }
1429
1430 if (dVar >= pPoints[iNumPoints - 1]) {
1431 return pVals[iNumPoints - 1];
1432 }
1433
1434 for (unsigned int i = 1; i < iNumPoints; i++) {
1435 if (dVar == pPoints[i]) {
1436 return pVals[i];
1437 }
1438 if (dVar < pPoints[i]) {
1439 doublereal dx = pPoints[i] - pPoints[i - 1];
1440 return ((dVar - pPoints[i - 1])*pVals[i]
1441 + (pPoints[i] - dVar)*pVals[i - 1])/dx;
1442 }
1443 }
1444
1445 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
1446 }
1447
1448 inline bool
bIsDifferentiable(void)1449 PiecewiseLinearDriveCaller::bIsDifferentiable(void) const
1450 {
1451 return true;
1452 }
1453
1454 inline doublereal
dGetP(const doublereal & dVar)1455 PiecewiseLinearDriveCaller::dGetP(const doublereal& dVar) const
1456 {
1457 if (dVar < pPoints[0] || dVar > pPoints[iNumPoints - 1]) {
1458 return 0.;
1459 }
1460
1461 if (dVar == pPoints[0]) {
1462 return (pVals[1] - pVals[0])/(pPoints[1] - pPoints[0])/2.;
1463 }
1464
1465 if (dVar == pPoints[iNumPoints - 1]) {
1466 return (pVals[iNumPoints - 1] - pVals[iNumPoints - 2])/(pPoints[iNumPoints - 1] - pPoints[iNumPoints - 2])/2.;
1467 }
1468
1469 for (unsigned int i = 1; i < iNumPoints; i++) {
1470 if (dVar == pPoints[i]) {
1471 doublereal dS1 = (pVals[i] - pVals[i - 1])/(pPoints[i] - pPoints[i - 1]);
1472 doublereal dS2 = (pVals[i + 1] - pVals[i])/(pPoints[i + 1] - pPoints[i]);
1473
1474 return (dS1 + dS2)/2.;
1475 }
1476
1477 if (dVar < pPoints[i]) {
1478 return (pVals[i] - pVals[i - 1])/(pPoints[i] - pPoints[i - 1]);
1479 }
1480 }
1481
1482 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
1483 }
1484
1485 /* PiecewiseLinearDriveCaller - end */
1486
1487 /* DriveArrayCaller - begin */
1488
1489 class DriveArrayCaller : public DriveCaller {
1490 public:
1491 typedef std::vector<const DriveCaller *> dcv_t;
1492
1493 private:
1494 dcv_t m_dc;
1495
1496 public:
1497 DriveArrayCaller(const DriveHandler* pDH, dcv_t& DC);
1498 virtual ~DriveArrayCaller(void);
1499
1500 /* Copia */
1501 virtual DriveCaller* pCopy(void) const;
1502
1503 /* Scrive il contributo del DriveCaller al file di restart */
1504 virtual std::ostream& Restart(std::ostream& out) const;
1505
1506 inline doublereal dGet(const doublereal& dVar) const;
1507 inline doublereal dGet(void) const;
1508
1509 /* this is about drives that are differentiable */
1510 virtual bool bIsDifferentiable(void) const;
1511 virtual doublereal dGetP(const doublereal& dVar) const;
1512 #if 0
1513 virtual inline doublereal dGetP(void) const;
1514 #endif
1515 };
1516
1517 inline doublereal
dGet(const doublereal & dVar)1518 DriveArrayCaller::dGet(const doublereal& dVar) const
1519 {
1520 doublereal d = 0.;
1521
1522 for (dcv_t::const_iterator i = m_dc.begin(); i != m_dc.end(); ++i) {
1523 ASSERT(*i != 0);
1524
1525 d += (*i)->dGet(dVar);
1526 }
1527
1528 return d;
1529 }
1530
1531 inline doublereal
dGet(void)1532 DriveArrayCaller::dGet(void) const
1533 {
1534 doublereal d = 0.;
1535
1536 for (dcv_t::const_iterator i = m_dc.begin(); i != m_dc.end(); ++i) {
1537 ASSERT(*i != 0);
1538
1539 d += (*i)->dGet();
1540 }
1541
1542 return d;
1543 }
1544
1545 inline bool
bIsDifferentiable(void)1546 DriveArrayCaller::bIsDifferentiable(void) const
1547 {
1548 for (dcv_t::const_iterator i = m_dc.begin(); i != m_dc.end(); ++i) {
1549 ASSERT(*i != 0);
1550
1551 if (!(*i)->bIsDifferentiable()) {
1552 return false;
1553 }
1554 }
1555
1556 return true;
1557 }
1558
1559 inline doublereal
dGetP(const doublereal & dVar)1560 DriveArrayCaller::dGetP(const doublereal& dVar) const
1561 {
1562 doublereal dP = 0.;
1563
1564 for (dcv_t::const_iterator i = m_dc.begin(); i != m_dc.end(); ++i) {
1565 ASSERT(*i != 0);
1566 ASSERT((*i)->bIsDifferentiable());
1567
1568 dP += (*i)->dGetP(dVar);
1569 }
1570
1571 return dP;
1572 }
1573
1574 /* DriveArrayCaller - end */
1575
1576 /* PeriodicDriveCaller - begin */
1577
1578 class PeriodicDriveCaller : public DriveCaller {
1579 protected:
1580 DriveOwner DO;
1581 doublereal dT0;
1582 doublereal dPeriod;
1583
1584 public:
1585 PeriodicDriveCaller(const DriveHandler* pDH,
1586 const DriveCaller *pDC, doublereal dT0, doublereal dPeriod);
1587 virtual ~PeriodicDriveCaller(void);
1588
1589 /* Scrive il contributo del DriveCaller al file di restart */
1590 virtual std::ostream& Restart(std::ostream& out) const;
1591
1592 /* Copia */
1593 virtual DriveCaller* pCopy(void) const;
1594
1595 inline doublereal dGet(void) const;
1596 inline doublereal dGet(const doublereal& dVar) const;
1597
1598 /* this is about drives that are differentiable */
1599 virtual bool bIsDifferentiable(void) const;
1600 virtual doublereal dGetP(const doublereal& dVar) const;
1601 };
1602
1603 inline doublereal
dGet(void)1604 PeriodicDriveCaller::dGet(void) const
1605 {
1606 doublereal dTime = pDrvHdl->dGetTime();
1607 if (dTime < dT0) {
1608 return 0.;
1609 }
1610 dTime -= dT0;
1611 dTime -= floor(dTime/dPeriod)*dPeriod;
1612 return DO.pGetDriveCaller()->dGet(dTime);
1613 }
1614
1615 inline doublereal
dGet(const doublereal & dVar)1616 PeriodicDriveCaller::dGet(const doublereal& dVar) const
1617 {
1618 if (dVar < dT0) {
1619 return 0.;
1620 }
1621 doublereal dTime = dVar - dT0;
1622 dTime -= floor(dTime/dPeriod)*dPeriod;
1623 return DO.pGetDriveCaller()->dGet(dTime);
1624 }
1625
1626 inline bool
bIsDifferentiable(void)1627 PeriodicDriveCaller::bIsDifferentiable(void) const
1628 {
1629 return DO.pGetDriveCaller()->bIsDifferentiable();
1630 }
1631
1632 inline doublereal
dGetP(const doublereal & dVar)1633 PeriodicDriveCaller::dGetP(const doublereal& dVar) const
1634 {
1635 if (dVar < dT0) {
1636 return 0.;
1637 }
1638 doublereal dTime = dVar - dT0;
1639 dTime -= floor(dTime/dPeriod)*dPeriod;
1640 return DO.pGetDriveCaller()->dGetP(dTime);
1641 }
1642
1643 /* PeriodicDriveCaller - end */
1644
1645 /* PostponedDriveCaller - begin */
1646
1647 class PostponedDriveCaller : public DriveCaller {
1648 protected:
1649 MBDynParser& HP;
1650 unsigned uDriveLabel;
1651 mutable DriveOwner DO;
1652
1653 void Check(void) const;
1654
1655 public:
1656 PostponedDriveCaller(MBDynParser& HP, unsigned uLabel);
1657 virtual ~PostponedDriveCaller(void);
1658
1659 /* Scrive il contributo del DriveCaller al file di restart */
1660 virtual std::ostream& Restart(std::ostream& out) const;
1661
1662 /* Copia */
1663 virtual DriveCaller* pCopy(void) const;
1664
1665 doublereal dGet(void) const;
1666 doublereal dGet(const doublereal& dVar) const;
1667
1668 /* this is about drives that are differentiable */
1669 virtual bool bIsDifferentiable(void) const;
1670 virtual doublereal dGetP(const doublereal& dVar) const;
1671 };
1672
1673 inline doublereal
dGet(void)1674 PostponedDriveCaller::dGet(void) const
1675 {
1676 Check();
1677 return DO.dGet();
1678 }
1679
1680 inline doublereal
dGet(const doublereal & dVar)1681 PostponedDriveCaller::dGet(const doublereal& dVar) const
1682 {
1683 Check();
1684 return DO.dGet(dVar);
1685 }
1686
1687 inline bool
bIsDifferentiable(void)1688 PostponedDriveCaller::bIsDifferentiable(void) const
1689 {
1690 Check();
1691 return DO.bIsDifferentiable();
1692 }
1693
1694 inline doublereal
dGetP(const doublereal & dVar)1695 PostponedDriveCaller::dGetP(const doublereal& dVar) const
1696 {
1697 Check();
1698 return DO.dGetP(dVar);
1699 }
1700
1701 /* PostponedDriveCaller - end */
1702
1703 /*----------------------------------------------------------------------------
1704 management of FileDriveCaller type
1705 ------------------------------------------------------------------------------
1706
1707 Coded by Luca Conti (May 2017)
1708 */
1709
1710 /*FileDriveCaller type reader: every content type must inherit
1711 from this struct and implement its own Read method*/
1712 struct FileDriveCallerTypeReader {
1713 virtual integer Read(const DataManager* pDM, MBDynParser& HP, FileDrive* pDrv) = 0;
~FileDriveCallerTypeReaderFileDriveCallerTypeReader1714 virtual ~FileDriveCallerTypeReader(void) { NO_OP; };
1715 };
1716
1717 /*bag of FileDriveCaller type - every type is registered inside
1718 of it by using SetFileDriveCallerType(...)*/
1719 typedef std::map<std::string,FileDriveCallerTypeReader*> FileDriveCallerTypeMap;
1720 extern FileDriveCallerTypeMap fileDriveCallerTypeMap;
1721
1722 /* FileDriveCaller type parsing checker: allows the parser
1723 to understand if the next keyword is a FileDriveCaller type */
1724 struct FileDriveCallerTypeWordSet : public HighParser::WordSet {
1725 virtual bool IsWord(const std::string& s) const;
1726 };
1727 typedef struct FileDriveCallerTypeWordSet FileDriveCallerTypeWordSet;
1728 extern FileDriveCallerTypeWordSet fileDriveCallerTypeWordSet;
1729
1730 /* registration function: call it to register a new FileDriveCaller type*/
1731 bool setFileDriveCallerType(const char *name, FileDriveCallerTypeReader *rf);
1732
1733 /*deallocation of all FileDriveCaller types in fileDriveCallerTypeMap, if any was added*/
1734 void DestroyFileDriveCallerTypes(void);
1735
1736 #endif /* DRIVE__H */
1737