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