1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/drive_.cc,v 1.118 2017/08/28 10:34:39 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 #include "mbconfig.h"           /* This goes first in every *.c,*.cc file */
33 
34 #include <limits>
35 #include <cmath>
36 #include <cfloat>
37 
38 #ifdef USE_MPI
39 #include "mbcomm.h"
40 #endif /* USE_MPI */
41 
42 #include "dataman.h"
43 #include "drive_.h"
44 #include "dofdrive.h"
45 #include "privdrive.h"
46 #include "ddrive.h"
47 #include "shdrive.h"
48 
49 #include "filedrv.h"
50 #include "fixedstep.h"
51 #include "varstep.h"
52 #include "sockdrv.h"
53 #include "streamdrive.h"
54 #include "socketstreamdrive.h"
55 #include "bufferstreamdrive.h"
56 
57 #ifdef USE_GINAC
58 #include "ginacdrive.h"
59 #endif // USE_GINAC
60 
61 #ifdef STATIC_MODULES
62 #ifdef USE_OCTAVE
63 #include "module-octave/module-octave.h"
64 #endif // USE_OCTAVE
65 #include "module-nodedistdrive/module-nodedistdrive.h"
66 #include "module-minmaxdrive/module-minmaxdrive.h"
67 #endif // STATIC_MODULES
68 
69 /* StringDriveCaller - begin */
70 
71 #ifdef USE_EE
StringDriveCaller(const DriveHandler * pDH,const std::string & sTmpStr,const ExpressionElement * expr)72 StringDriveCaller::StringDriveCaller(const DriveHandler* pDH,
73 	const std::string& sTmpStr, const ExpressionElement *expr)
74 : DriveCaller(pDH), sEvalStr(sTmpStr), m_expr(new SharedExpr(expr))
75 {
76 	ASSERT(!sEvalStr.empty());
77 	ASSERT(m_expr->Get() != 0);
78 }
79 
80 
StringDriveCaller(const DriveHandler * pDH,const std::string & sTmpStr,SharedExprPtr_t expr)81 StringDriveCaller::StringDriveCaller(const DriveHandler* pDH,
82 	const std::string& sTmpStr, SharedExprPtr_t expr)
83 : DriveCaller(pDH), sEvalStr(sTmpStr), m_expr(expr)
84 {
85 	ASSERT(!sEvalStr.empty());
86 	ASSERT(m_expr->Get() != 0);
87 }
88 
89 
~StringDriveCaller(void)90 StringDriveCaller::~StringDriveCaller(void)
91 {
92 	ASSERT(m_expr->Get() != 0);
93 }
94 
95 
96 /* Copia */
97 DriveCaller *
pCopy(void) const98 StringDriveCaller::pCopy(void) const
99 {
100 	DriveCaller* pDC = 0;
101 
102 	SAFENEWWITHCONSTRUCTOR(pDC,
103 		StringDriveCaller,
104 		StringDriveCaller(pDrvHdl, sEvalStr, m_expr->pCopy()));
105 
106 	return pDC;
107 }
108 
109 #else // ! USE_EE
110 
StringDriveCaller(const DriveHandler * pDH,const std::string & sTmpStr)111 StringDriveCaller::StringDriveCaller(const DriveHandler* pDH,
112 	const std::string& sTmpStr)
113 : DriveCaller(pDH), sEvalStr(sTmpStr)
114 {
115 	ASSERT(!sEvalStr.empty());
116 }
117 
118 
~StringDriveCaller(void)119 StringDriveCaller::~StringDriveCaller(void)
120 {
121 	NO_OP;
122 }
123 
124 DriveCaller *
pCopy(void) const125 StringDriveCaller::pCopy(void) const
126 {
127 	DriveCaller* pDC = 0;
128 	SAFENEWWITHCONSTRUCTOR(pDC,
129 		StringDriveCaller,
130 		StringDriveCaller(pDrvHdl, sEvalStr));
131 
132 	return pDC;
133 }
134 
135 #endif // ! USE_EE
136 
137 
138 /* Scrive il contributo del DriveCaller al file di restart */
139 std::ostream&
Restart(std::ostream & out) const140 StringDriveCaller::Restart(std::ostream& out) const
141 {
142 	return out << "string, \"" << sEvalStr << "\"";
143 }
144 
145 /* StringDriveCaller - end */
146 
147 
148 /* TimeDriveCaller - begin */
149 
TimeDriveCaller(const DriveHandler * pDH)150 TimeDriveCaller::TimeDriveCaller(const DriveHandler* pDH)
151 : DriveCaller(pDH)
152 {
153 	NO_OP;
154 }
155 
~TimeDriveCaller(void)156 TimeDriveCaller::~TimeDriveCaller(void)
157 {
158 	NO_OP;
159 }
160 
161 /* Copia */
162 DriveCaller *
pCopy(void) const163 TimeDriveCaller::pCopy(void) const
164 {
165 	DriveCaller* pDC = 0;
166 	SAFENEWWITHCONSTRUCTOR(pDC, TimeDriveCaller, TimeDriveCaller(pDrvHdl));
167 	return pDC;
168 }
169 
170 /* Scrive il contributo del DriveCaller al file di restart */
171 std::ostream&
Restart(std::ostream & out) const172 TimeDriveCaller::Restart(std::ostream& out) const
173 {
174 	return out << "time";
175 }
176 
177 /* TimeDriveCaller - end */
178 
179 
180 /* TimeStepDriveCaller - begin */
181 
TimeStepDriveCaller(const DriveHandler * pDH)182 TimeStepDriveCaller::TimeStepDriveCaller(const DriveHandler* pDH)
183 : DriveCaller(pDH)
184 {
185 	NO_OP;
186 }
187 
~TimeStepDriveCaller(void)188 TimeStepDriveCaller::~TimeStepDriveCaller(void)
189 {
190 	NO_OP;
191 }
192 
193 /* Copia */
194 DriveCaller *
pCopy(void) const195 TimeStepDriveCaller::pCopy(void) const
196 {
197 	DriveCaller* pDC = 0;
198 	SAFENEWWITHCONSTRUCTOR(pDC, TimeStepDriveCaller, TimeStepDriveCaller(pDrvHdl));
199 	return pDC;
200 }
201 
202 /* Scrive il contributo del DriveCaller al file di restart */
203 std::ostream&
Restart(std::ostream & out) const204 TimeStepDriveCaller::Restart(std::ostream& out) const
205 {
206 	return out << "timestep";
207 }
208 
209 /* TimeStepDriveCaller - end */
210 
211 
212 /* MultDriveCaller - begin */
213 
MultDriveCaller(const DriveHandler * pDH,const DriveCaller * pDC1,const DriveCaller * pDC2)214 MultDriveCaller::MultDriveCaller(const DriveHandler *pDH,
215 	const DriveCaller* pDC1, const DriveCaller *pDC2)
216 : DriveCaller(pDH),
217 DO1(pDC1), DO2(pDC2)
218 {
219 	NO_OP;
220 }
221 
~MultDriveCaller(void)222 MultDriveCaller::~MultDriveCaller(void)
223 {
224 	NO_OP;
225 }
226 
227 /* Copia */
228 DriveCaller *
pCopy(void) const229 MultDriveCaller::pCopy(void) const
230 {
231 	DriveCaller* pDC = 0;
232 	SAFENEWWITHCONSTRUCTOR(pDC, MultDriveCaller,
233 		MultDriveCaller(pDrvHdl,
234 			DO1.pGetDriveCaller()->pCopy(), DO2.pGetDriveCaller()->pCopy()));
235 	return pDC;
236 }
237 
238 /* Scrive il contributo del DriveCaller al file di restart */
239 std::ostream&
Restart(std::ostream & out) const240 MultDriveCaller::Restart(std::ostream& out) const
241 {
242 	return out << "mult, ",
243 		DO1.pGetDriveCaller()->Restart(out) << ", ";
244 		DO2.pGetDriveCaller()->Restart(out);
245 }
246 
247 /* MultDriveCaller - end */
248 
249 
250 /* ConstDriveCaller - begin */
251 
ConstDriveCaller(doublereal d)252 ConstDriveCaller::ConstDriveCaller(doublereal d)
253 : DriveCaller(0), dConst(d)
254 {
255 	NO_OP;
256 }
257 
~ConstDriveCaller(void)258 ConstDriveCaller::~ConstDriveCaller(void)
259 {
260 	NO_OP;
261 }
262 
263 /* Copia */
264 DriveCaller*
pCopy(void) const265 ConstDriveCaller::pCopy(void) const
266 {
267 	DriveCaller* pDC = 0;
268 	SAFENEWWITHCONSTRUCTOR(pDC, ConstDriveCaller, ConstDriveCaller(dConst));
269 	return pDC;
270 }
271 
272 /* Scrive il contributo del DriveCaller al file di restart */
273 std::ostream&
Restart(std::ostream & out) const274 ConstDriveCaller::Restart(std::ostream& out) const
275 {
276 	return out << " const, " << dConst;
277 }
278 
279 /* ConstDriveCaller - end */
280 
281 
282 /* LinearDriveCaller - begin */
283 
LinearDriveCaller(const DriveHandler * pDH,doublereal d0,doublereal d1)284 LinearDriveCaller::LinearDriveCaller(const DriveHandler* pDH,
285 	doublereal d0, doublereal d1)
286 : DriveCaller(pDH), dC0(d0), dC1(d1)
287 {
288 	NO_OP;
289 }
290 
~LinearDriveCaller(void)291 LinearDriveCaller::~LinearDriveCaller(void)
292 {
293 	NO_OP;
294 }
295 
296 /* Copia */
297 DriveCaller *
pCopy(void) const298 LinearDriveCaller::pCopy(void) const
299 {
300 	DriveCaller* pDC = 0;
301 	SAFENEWWITHCONSTRUCTOR(pDC, LinearDriveCaller, LinearDriveCaller(pDrvHdl, dC0, dC1));
302 	return pDC;
303 }
304 
305 /* Scrive il contributo del DriveCaller al file di restart */
306 std::ostream&
Restart(std::ostream & out) const307 LinearDriveCaller::Restart(std::ostream& out) const
308 {
309 	return out << " linear, " << dC0 << ", " << dC1;
310 }
311 
312 /* LinearDriveCaller - end */
313 
314 
315 /* ParabolicDriveCaller - begin */
316 
ParabolicDriveCaller(const DriveHandler * pDH,doublereal d0,doublereal d1,doublereal d2)317 ParabolicDriveCaller::ParabolicDriveCaller(const DriveHandler* pDH,
318 	doublereal d0, doublereal d1, doublereal d2)
319 : DriveCaller(pDH), dC0(d0), dC1(d1), dC2(d2)
320 {
321 	NO_OP;
322 }
323 
~ParabolicDriveCaller(void)324 ParabolicDriveCaller::~ParabolicDriveCaller(void)
325 {
326 	NO_OP;
327 }
328 
329 /* Copia */
330 DriveCaller *
pCopy(void) const331 ParabolicDriveCaller::pCopy(void) const
332 {
333 	DriveCaller* pDC = 0;
334 	SAFENEWWITHCONSTRUCTOR(pDC, ParabolicDriveCaller, ParabolicDriveCaller(pDrvHdl, dC0, dC1, dC2));
335 	return pDC;
336 }
337 
338 /* Scrive il contributo del DriveCaller al file di restart */
339 std::ostream&
Restart(std::ostream & out) const340 ParabolicDriveCaller::Restart(std::ostream& out) const
341 {
342 	return out <<  " parabolic, " << dC0 << ", " << dC1 << ", " << dC2;
343 }
344 
345 /* ParabolicDriveCaller - end */
346 
347 
348 /* CubicDriveCaller - begin */
349 
CubicDriveCaller(const DriveHandler * pDH,doublereal d0,doublereal d1,doublereal d2,doublereal d3)350 CubicDriveCaller::CubicDriveCaller(const DriveHandler* pDH,
351 	doublereal d0, doublereal d1,
352 	doublereal d2, doublereal d3)
353 : DriveCaller(pDH), dC0(d0), dC1(d1), dC2(d2), dC3(d3)
354 {
355 	NO_OP;
356 }
357 
~CubicDriveCaller(void)358 CubicDriveCaller::~CubicDriveCaller(void)
359 {
360    NO_OP;
361 }
362 
363 /* Copia */
364 DriveCaller *
pCopy(void) const365 CubicDriveCaller::pCopy(void) const
366 {
367 	DriveCaller* pDC = 0;
368 	SAFENEWWITHCONSTRUCTOR(pDC, CubicDriveCaller, CubicDriveCaller(pDrvHdl, dC0, dC1, dC2, dC3));
369 	return pDC;
370 }
371 
372 /* Scrive il contributo del DriveCaller al file di restart */
373 std::ostream&
Restart(std::ostream & out) const374 CubicDriveCaller::Restart(std::ostream& out) const
375 {
376 	return out << " cubic, "
377 		<< dC0 << ", " << dC1 << ", " << dC2 << ", " << dC3;
378 }
379 
380 /* CubicDriveCaller - end */
381 
382 
383 /* StepDriveCaller - begin */
384 
StepDriveCaller(const DriveHandler * pDH,doublereal d1,doublereal d2,doublereal d3)385 StepDriveCaller::StepDriveCaller(const DriveHandler* pDH,
386 	doublereal d1, doublereal d2, doublereal d3)
387 : DriveCaller(pDH),
388 dStepTime(d1), dStepValue(d2), dInitialValue(d3)
389 {
390 	NO_OP;
391 }
392 
~StepDriveCaller(void)393 StepDriveCaller::~StepDriveCaller(void)
394 {
395 	NO_OP;
396 }
397 
398 /* Copia */
399 DriveCaller *
pCopy(void) const400 StepDriveCaller::pCopy(void) const
401 {
402 	DriveCaller* pDC = 0;
403 	SAFENEWWITHCONSTRUCTOR(pDC,
404 		StepDriveCaller,
405 		StepDriveCaller(pDrvHdl, dStepTime, dStepValue, dInitialValue));
406 	return pDC;
407 }
408 
409 /* Scrive il contributo del DriveCaller al file di restart */
410 std::ostream&
Restart(std::ostream & out) const411 StepDriveCaller::Restart(std::ostream& out) const
412 {
413 	return out
414 		<< " step, " << dStepTime
415 		<< ", " << dStepValue
416 		<< ", " << dInitialValue;
417 }
418 
419 /* StepDriveCaller - end */
420 
421 
422 /* DoubleStepDriveCaller - begin */
423 
DoubleStepDriveCaller(const DriveHandler * pDH,doublereal d1,doublereal d2,doublereal d3,doublereal d4)424 DoubleStepDriveCaller::DoubleStepDriveCaller(const DriveHandler* pDH,
425 	doublereal d1, doublereal d2, doublereal d3, doublereal d4)
426 : DriveCaller(pDH), dStepTime(d1), dStepValue(d2),
427 dEndStepTime(d3), dInitialValue(d4)
428 {
429 	NO_OP;
430 }
431 
~DoubleStepDriveCaller(void)432 DoubleStepDriveCaller::~DoubleStepDriveCaller(void)
433 {
434 	NO_OP;
435 }
436 
437 
438 /* Copia */
439 DriveCaller *
pCopy(void) const440 DoubleStepDriveCaller::pCopy(void) const
441 {
442 	DriveCaller* pDC = 0;
443 	SAFENEWWITHCONSTRUCTOR(pDC,
444 		DoubleStepDriveCaller,
445 		DoubleStepDriveCaller(pDrvHdl, dStepTime, dStepValue, dEndStepTime, dInitialValue));
446 	return pDC;
447 }
448 
449 
450 /* Scrive il contributo del DriveCaller al file di restart */
451 std::ostream&
Restart(std::ostream & out) const452 DoubleStepDriveCaller::Restart(std::ostream& out) const
453 {
454 	return out
455 		<< " double step, " << dStepTime
456 		<< ", " << dEndStepTime
457 		<< ", " << dStepValue
458 		<< ", " << dInitialValue;
459 }
460 
461 /* DoubleStepDriveCaller - end */
462 
463 
464 /* RampDriveCaller - begin */
465 
RampDriveCaller(const DriveHandler * pDH,doublereal d1,doublereal d2,doublereal d3,doublereal d4)466 RampDriveCaller::RampDriveCaller(const DriveHandler* pDH,
467 	doublereal d1, doublereal d2, doublereal d3, doublereal d4)
468 : DriveCaller(pDH), dSlope(d1), dStartTime(d2), dEndTime(d3), dInitialValue(d4)
469 {
470 	NO_OP;
471 }
472 
~RampDriveCaller(void)473 RampDriveCaller::~RampDriveCaller(void)
474 {
475 	NO_OP;
476 }
477 
478 /* Copia */
479 DriveCaller *
pCopy(void) const480 RampDriveCaller::pCopy(void) const
481 {
482 	DriveCaller* pDC = 0;
483 	SAFENEWWITHCONSTRUCTOR(pDC,
484 		RampDriveCaller,
485 		RampDriveCaller(pDrvHdl, dSlope, dStartTime, dEndTime, dInitialValue));
486 	return pDC;
487 }
488 
489 /* Scrive il contributo del DriveCaller al file di restart */
490 std::ostream&
Restart(std::ostream & out) const491 RampDriveCaller::Restart(std::ostream& out) const
492 {
493 	return out
494 		<< "ramp, " << dSlope
495 		<< ", " << dStartTime
496 		<< ", " << dEndTime
497 		<< ", " << dInitialValue;
498 }
499 
500 /* RampDriveCaller - end */
501 
502 
503 /* DoubleRampDriveCaller - begin */
504 
DoubleRampDriveCaller(const DriveHandler * pDH,doublereal d1,doublereal d2,doublereal d3,doublereal d4,doublereal d5,doublereal d6,doublereal d7)505 DoubleRampDriveCaller::DoubleRampDriveCaller(const DriveHandler* pDH,
506 	doublereal d1, doublereal d2, doublereal d3,
507 	doublereal d4, doublereal d5, doublereal d6,
508 	doublereal d7)
509 : DriveCaller(pDH),
510 dAscendingSlope(d1), dAscendingStartTime(d2), dAscendingEndTime(d3),
511 dDescendingSlope(d4), dDescendingStartTime(d5), dDescendingEndTime(d6),
512 dInitialValue(d7)
513 {
514 	NO_OP;
515 }
516 
~DoubleRampDriveCaller(void)517 DoubleRampDriveCaller::~DoubleRampDriveCaller(void)
518 {
519 	NO_OP;
520 }
521 
522 /* Copia */
523 DriveCaller *
pCopy(void) const524 DoubleRampDriveCaller::pCopy(void) const
525 {
526 	DriveCaller* pDC = 0;
527 	SAFENEWWITHCONSTRUCTOR(pDC,
528 		DoubleRampDriveCaller,
529 		DoubleRampDriveCaller(pDrvHdl, dAscendingSlope, dAscendingStartTime, dAscendingEndTime,
530 			dDescendingSlope, dDescendingStartTime, dDescendingEndTime, dInitialValue));
531 	return pDC;
532 }
533 
534 /* Scrive il contributo del DriveCaller al file di restart */
535 std::ostream&
Restart(std::ostream & out) const536 DoubleRampDriveCaller::Restart(std::ostream& out) const
537 {
538 	return out
539 		<< " double ramp, " << dAscendingSlope
540 		<< ", " << dAscendingStartTime
541 		<< ", " << dAscendingEndTime
542 		<< ", " << dDescendingSlope
543 		<< ", " << dDescendingStartTime
544 		<< ", " << dDescendingEndTime
545 		<< ", " << dInitialValue;
546 }
547 
548 /* DoubleRampDriveCaller - end */
549 
550 
551 /* SineDriveCaller - begin */
552 
SineDriveCaller(const DriveHandler * pDH,doublereal d1,doublereal d2,doublereal d3,integer iNumCyc,doublereal d4)553 SineDriveCaller::SineDriveCaller(const DriveHandler* pDH,
554 	doublereal d1, doublereal d2, doublereal d3,
555 	integer iNumCyc, doublereal d4)
556 : DriveCaller(pDH),
557 dStartTime(d1), dOmega(d2), dAmplitude(d3),
558 iNumCycles(iNumCyc), dInitialValue(d4), bNeverEnd(false)
559 {
560 	/* Onde di seno che partono da zero ed arrivano a0 */
561 	if (iNumCycles > 0) {
562 		dEndTime = dStartTime + 2.*M_PI/dOmega*(doublereal(iNumCycles) - .5);
563 		dFinalValue = dInitialValue;
564 
565 	/* Onde di seno che continuano all'infinito */
566 	} else if (iNumCycles == 0) {
567 		dEndTime = 0.;
568 		bNeverEnd = true;
569 
570 	/* Onde di seno che partono da 0 ed arrivano ad 1
571 	 * con tangente orizzontale */
572 	} else {
573 		dEndTime = dStartTime + 2.*M_PI/dOmega*(doublereal(-iNumCycles) - .75);
574 		dFinalValue = dInitialValue + dAmplitude;
575 	}
576 }
577 
~SineDriveCaller(void)578 SineDriveCaller::~SineDriveCaller(void)
579 {
580    NO_OP;
581 }
582 
583 /* Copia */
584 DriveCaller *
pCopy(void) const585 SineDriveCaller::pCopy(void) const
586 {
587 	DriveCaller* pDC = 0;
588 	SAFENEWWITHCONSTRUCTOR(pDC,
589 		SineDriveCaller,
590 		SineDriveCaller(pDrvHdl, dStartTime, dOmega, dAmplitude, iNumCycles, dInitialValue));
591 	return pDC;
592 }
593 
594 /* Scrive il contributo del DriveCaller al file di restart */
595 std::ostream&
Restart(std::ostream & out) const596 SineDriveCaller::Restart(std::ostream& out) const
597 {
598 	return out
599 		<< " sine, " << dStartTime
600 		<< ", " << dOmega
601 		<< ", " << dAmplitude
602 		<< ", " << iNumCycles
603 		<< ", " << dInitialValue;
604 }
605 
606 /* SineDriveCaller - end */
607 
608 
609 /* FourierSeriesDriveCaller - begin */
610 
FourierSeriesDriveCaller(const DriveHandler * pDH,doublereal dStartTime,doublereal dOmega,std::vector<doublereal> & a,integer iNumCyc,doublereal dInitialValue)611 FourierSeriesDriveCaller::FourierSeriesDriveCaller(const DriveHandler* pDH,
612 	doublereal dStartTime,
613 	doublereal dOmega,
614 	std::vector<doublereal>& a,
615 	integer iNumCyc,
616 	doublereal dInitialValue)
617 : DriveCaller(pDH),
618 dStartTime(dStartTime),
619 dOmega(dOmega),
620 iNumCycles(iNumCyc),
621 dInitialValue(dInitialValue),
622 bNeverEnd(false)
623 {
624 	ASSERT(iNumCycles >= 0);
625 
626 	if (iNumCycles > 0) {
627 		dEndTime = dStartTime
628 			+ 2.*M_PI/dOmega*doublereal(iNumCycles);
629 
630 	/* Onde di coseno che continuano all'infinito */
631 	} else if (iNumCycles == 0) {
632 		dEndTime = 0.;
633 		bNeverEnd = true;
634 	}
635 
636 	amplitudes.resize(a.size());
637 	for (unsigned i = 0; i < a.size(); i++) {
638 		amplitudes[i] = a[i];
639 	}
640 }
641 
~FourierSeriesDriveCaller(void)642 FourierSeriesDriveCaller::~FourierSeriesDriveCaller(void)
643 {
644 	NO_OP;
645 }
646 
647 /* Copia */
648 DriveCaller *
pCopy(void) const649 FourierSeriesDriveCaller::pCopy(void) const
650 {
651 	DriveCaller* pDC = 0;
652 
653 	SAFENEWWITHCONSTRUCTOR(pDC,
654 		FourierSeriesDriveCaller,
655 		FourierSeriesDriveCaller(pDrvHdl,
656 			dStartTime,
657 			dOmega,
658 			amplitudes,
659 			iNumCycles,
660 			dInitialValue));
661 	return pDC;
662 }
663 
664 
665 /* Scrive il contributo del DriveCaller al file di restart */
666 std::ostream&
Restart(std::ostream & out) const667 FourierSeriesDriveCaller::Restart(std::ostream& out) const
668 {
669 	out
670 		<< " fourier series, "
671 		<< dStartTime << ", "
672 		<< dOmega << ", "
673 		<< amplitudes.size()/2 << ", "
674 		<< 2.*amplitudes[0] << ", ";
675 
676 	for (unsigned i = 1; i < amplitudes.size(); i++) {
677 		out << amplitudes[i] << ", ";
678 	}
679 
680 	out
681 		<< iNumCycles << ", "
682 		<< dInitialValue;
683 
684 	return out;
685 }
686 
687 /* FourierSeriesDriveCaller - end */
688 
689 
690 /* CosineDriveCaller - begin */
691 
CosineDriveCaller(const DriveHandler * pDH,doublereal d1,doublereal d2,doublereal d3,integer iNumCyc,doublereal d4)692 CosineDriveCaller::CosineDriveCaller(const DriveHandler* pDH,
693 	doublereal d1, doublereal d2,
694 	doublereal d3,
695 	integer iNumCyc, doublereal d4)
696 : DriveCaller(pDH),
697 dStartTime(d1), dOmega(d2), dAmplitude(d3),
698 iNumCycles(iNumCyc), dInitialValue(d4), bNeverEnd(false)
699 {
700 	/* Onde di coseno che partono da zero ed arrivano a 0 */
701 	if (iNumCycles > 0) {
702 		dEndTime = dStartTime + 2.*M_PI/dOmega*doublereal(iNumCycles);
703 		dFinalValue = dInitialValue;
704 
705 	/* Onde di coseno che continuano all'infinito */
706 	} else if (iNumCycles == 0) {
707 		dEndTime = 0.;
708 		bNeverEnd = true;
709 
710 	/* Onde di coseno che partono da 0 ed arrivano ad 1
711 	 * con tangente orizzontale */
712 	} else {
713 		dEndTime = dStartTime + 2.*M_PI/dOmega*(doublereal(-iNumCycles) - .5);
714 		dFinalValue = dInitialValue + 2.*dAmplitude;
715 	}
716 }
717 
~CosineDriveCaller(void)718 CosineDriveCaller::~CosineDriveCaller(void)
719 {
720 	NO_OP;
721 }
722 
723 /* Copia */
724 DriveCaller*
pCopy(void) const725 CosineDriveCaller::pCopy(void) const
726 {
727 	DriveCaller* pDC = 0;
728 	SAFENEWWITHCONSTRUCTOR(pDC,
729 		CosineDriveCaller,
730 		CosineDriveCaller(pDrvHdl, dStartTime, dOmega, dAmplitude, iNumCycles, dInitialValue));
731 	return pDC;
732 }
733 
734 /* Scrive il contributo del DriveCaller al file di restart */
735 std::ostream&
Restart(std::ostream & out) const736 CosineDriveCaller::Restart(std::ostream& out) const
737 {
738 	return out
739 		<< " cosine, " << dStartTime
740 		<< ", " << dOmega
741 		<< ", " << dAmplitude
742 		<< ", " << iNumCycles
743 		<< ", " << dInitialValue;
744 }
745 
746 /* CosineDriveCaller - end */
747 
748 
749 /* TanhDriveCaller - begin */
750 
TanhDriveCaller(const DriveHandler * pDH,doublereal ds,doublereal da,doublereal db,doublereal di)751 TanhDriveCaller::TanhDriveCaller(const DriveHandler* pDH,
752 	doublereal ds, doublereal da,
753 	doublereal db, doublereal di)
754 : DriveCaller(pDH),
755 dStart(ds), dA(da), dB(db), dInitialValue(di)
756 {
757 	NO_OP;
758 }
759 
~TanhDriveCaller(void)760 TanhDriveCaller::~TanhDriveCaller(void)
761 {
762 	NO_OP;
763 }
764 
765 /* Copia */
766 DriveCaller*
pCopy(void) const767 TanhDriveCaller::pCopy(void) const
768 {
769 	DriveCaller* pDC = 0;
770 	SAFENEWWITHCONSTRUCTOR(pDC,
771 		TanhDriveCaller,
772 		TanhDriveCaller(pDrvHdl, dStart, dA, dB, dInitialValue));
773 	return pDC;
774 }
775 
776 /* Scrive il contributo del DriveCaller al file di restart */
777 std::ostream&
Restart(std::ostream & out) const778 TanhDriveCaller::Restart(std::ostream& out) const
779 {
780 	return out
781 		<< " tanh, " << dStart
782 		<< ", " << dA
783 		<< ", " << dB
784 		<< ", " << dInitialValue;
785 }
786 
787 /* TanhDriveCaller - end */
788 
789 
790 /* FreqSweepDriveCaller - begin */
791 
FreqSweepDriveCaller(const DriveHandler * pDH,doublereal d1,const DriveCaller * pOmega,const DriveCaller * pAmplitude,doublereal d2,doublereal d3,doublereal d4)792 FreqSweepDriveCaller::FreqSweepDriveCaller(const DriveHandler* pDH,
793 	doublereal d1,
794 	const DriveCaller* pOmega,
795 	const DriveCaller* pAmplitude,
796 	doublereal d2,
797 	doublereal d3,
798 	doublereal d4)
799 : DriveCaller(pDH),
800 dStartTime(d1), pOmega(pOmega),
801 pAmplitude(pAmplitude),
802 dInitialValue(d2), dEndTime(d3), dFinalValue(d4),
803 bNeverEnd(false)
804 {
805 	ASSERT(pOmega != 0);
806 	ASSERT(pAmplitude != 0);
807 
808 	if (dEndTime <= dStartTime) {
809 		bNeverEnd = true;
810 	}
811 }
812 
~FreqSweepDriveCaller(void)813 FreqSweepDriveCaller::~FreqSweepDriveCaller(void)
814 {
815 	if (pOmega) {
816 		SAFEDELETE(pOmega);
817 	}
818 
819 	if (pAmplitude) {
820 		SAFEDELETE(pAmplitude);
821 	}
822 }
823 
824 /* Copia */
825 DriveCaller *
pCopy(void) const826 FreqSweepDriveCaller::pCopy(void) const
827 {
828 	DriveCaller* pDC = 0;
829 	SAFENEWWITHCONSTRUCTOR(pDC,
830 		FreqSweepDriveCaller,
831 		FreqSweepDriveCaller(pDrvHdl, dStartTime, pOmega->pCopy(),
832 			pAmplitude->pCopy(), dInitialValue, dEndTime, dFinalValue));
833 	return pDC;
834 }
835 
836 /* Scrive il contributo del DriveCaller al file di restart */
837 std::ostream&
Restart(std::ostream & out) const838 FreqSweepDriveCaller::Restart(std::ostream& out) const
839 {
840 	out
841 		<< " frequency sweep, " << dStartTime
842 		<< ", ", pOmega->Restart(out)
843 		<< ", ", pAmplitude->Restart(out)
844 		<< ", " << dInitialValue
845 		<< ", " << dEndTime
846 		<< ", " << dFinalValue;
847 	return out;
848 }
849 
850 /* FreqSweepDriveCaller - end */
851 
852 
853 /* ExpDriveCaller - begin */
854 
ExpDriveCaller(const DriveHandler * pDH,doublereal dA,doublereal dT,doublereal dS,doublereal dI)855 ExpDriveCaller::ExpDriveCaller(const DriveHandler* pDH,
856 	doublereal dA, doublereal dT,
857 	doublereal dS, doublereal dI)
858 : DriveCaller(pDH),
859 dAmplitude(dA), dTimeConst(dT), dStartTime(dS), dInitialValue(dI)
860 {
861 	NO_OP;
862 }
863 
~ExpDriveCaller(void)864 ExpDriveCaller::~ExpDriveCaller(void)
865 {
866 	NO_OP;
867 }
868 
869 /* Copia */
870 DriveCaller*
pCopy(void) const871 ExpDriveCaller::pCopy(void) const
872 {
873 	DriveCaller* pDC = 0;
874 	SAFENEWWITHCONSTRUCTOR(pDC,
875 		ExpDriveCaller,
876 		ExpDriveCaller(pDrvHdl, dAmplitude, dTimeConst, dStartTime, dInitialValue));
877 	return pDC;
878 }
879 
880 /* Scrive il contributo del DriveCaller al file di restart */
881 std::ostream&
Restart(std::ostream & out) const882 ExpDriveCaller::Restart(std::ostream& out) const
883 {
884 	return out
885 		<< " exponential, " << dAmplitude
886 		<< ", " << dTimeConst
887 		<< ", " << dStartTime
888 		<< ", " << dInitialValue;
889 }
890 
891 /* ExpDriveCaller - end */
892 
893 
894 /* RandDriveCaller - begin */
895 
RandDriveCaller(const DriveHandler * pDH,doublereal dA,doublereal dR,doublereal dS,doublereal dE,integer iS)896 RandDriveCaller::RandDriveCaller(const DriveHandler* pDH,
897 	doublereal dA, doublereal dR,
898 	doublereal dS, doublereal dE, integer iS)
899 : DriveCaller(pDH), dAmplitude(dA), dRefVal(dR),
900 dStartTime(dS), dEndTime(dE), iSteps(iS)
901 {
902 	iBase = rand();
903 	iRandDriveNumber = pDrvHdl->iRandInit(iSteps);
904 }
905 
~RandDriveCaller(void)906 RandDriveCaller::~RandDriveCaller(void)
907 {
908 	NO_OP;
909 }
910 
911 /* Copia */
912 DriveCaller *
pCopy(void) const913 RandDriveCaller::pCopy(void) const
914 {
915 	DriveCaller* pDC = 0;
916 	SAFENEWWITHCONSTRUCTOR(pDC,
917 		RandDriveCaller,
918 		RandDriveCaller(pDrvHdl, dAmplitude, dRefVal, dStartTime, dEndTime, iSteps));
919 	return pDC;
920 }
921 
922 /* Scrive il contributo del DriveCaller al file di restart */
923 std::ostream&
Restart(std::ostream & out) const924 RandDriveCaller::Restart(std::ostream& out) const
925 {
926 	out
927 		<< " random, " << dAmplitude
928 		<< ", " << dRefVal
929 		<< ", " << dStartTime
930 		<< ", " << dEndTime;
931 	if (iSteps > 1) {
932 		out << ", steps, " << iSteps;
933 	}
934 	return out;
935 }
936 
937 /* RandDriveCaller - end */
938 
939 
940 /* MeterDriveCaller - begin */
941 
MeterDriveCaller(const DriveHandler * pDH,doublereal dS,doublereal dE,integer iS)942 MeterDriveCaller::MeterDriveCaller(const DriveHandler* pDH,
943 	doublereal dS, doublereal dE, integer iS)
944 : DriveCaller(pDH),
945 dStartTime(dS),
946 dEndTime(dE),
947 iSteps(iS)
948 {
949 	iMeterDriveNumber = pDrvHdl->iMeterInit(iSteps);
950 }
951 
~MeterDriveCaller(void)952 MeterDriveCaller::~MeterDriveCaller(void)
953 {
954 	NO_OP;
955 }
956 
957 /* Copia */
958 DriveCaller *
pCopy(void) const959 MeterDriveCaller::pCopy(void) const
960 {
961 	DriveCaller* pDC = 0;
962 	SAFENEWWITHCONSTRUCTOR(pDC,
963 		MeterDriveCaller,
964 		MeterDriveCaller(pDrvHdl, dStartTime, dEndTime, iSteps));
965 	return pDC;
966 }
967 
968 /* Scrive il contributo del DriveCaller al file di restart */
969 std::ostream&
Restart(std::ostream & out) const970 MeterDriveCaller::Restart(std::ostream& out) const
971 {
972 	out
973 		<< " meter, " << dStartTime
974 		<< ", " << dEndTime;
975 	if (iSteps > 1) {
976 		out << ", steps, " << iSteps;
977 	}
978 	return out;
979 }
980 
981 /* MeterDriveCaller - end */
982 
983 
984 /* ClosestNextDriveCaller - begin */
985 
ClosestNextDriveCaller(const DriveHandler * pDH,doublereal dS,doublereal dE,const DriveCaller * pIncrement)986 ClosestNextDriveCaller::ClosestNextDriveCaller(const DriveHandler* pDH,
987 	doublereal dS, doublereal dE, const DriveCaller *pIncrement)
988 : DriveCaller(pDH),
989 dStartTime(dS), dEndTime(dE),
990 pIncrement(pIncrement)
991 {
992 	iDriveNumber = pDrvHdl->iClosestNextInit(pIncrement, dStartTime);
993 }
994 
~ClosestNextDriveCaller(void)995 ClosestNextDriveCaller::~ClosestNextDriveCaller(void)
996 {
997 	NO_OP;
998 }
999 
1000 /* Copia */
1001 DriveCaller *
pCopy(void) const1002 ClosestNextDriveCaller::pCopy(void) const
1003 {
1004 	DriveCaller* pDC = 0;
1005 	SAFENEWWITHCONSTRUCTOR(pDC,
1006 		ClosestNextDriveCaller,
1007 		ClosestNextDriveCaller(pDrvHdl, dStartTime, dEndTime,
1008 		pIncrement->pCopy()));
1009 	return pDC;
1010 }
1011 
1012 /* Scrive il contributo del DriveCaller al file di restart */
1013 std::ostream&
Restart(std::ostream & out) const1014 ClosestNextDriveCaller::Restart(std::ostream& out) const
1015 {
1016 	out
1017 		<< " closest next, " << dStartTime
1018 		<< ", " << dEndTime
1019 		<< ", ", pIncrement->Restart(out);
1020 
1021 	return out;
1022 }
1023 
1024 /* ClosestNextDriveCaller - end */
1025 
1026 
1027 /* DirectDriveCaller - begin */
1028 
DirectDriveCaller(const DriveHandler * pDH)1029 DirectDriveCaller::DirectDriveCaller(const DriveHandler* pDH)
1030 : DriveCaller(pDH)
1031 {
1032 	NO_OP;
1033 }
1034 
~DirectDriveCaller(void)1035 DirectDriveCaller::~DirectDriveCaller(void)
1036 {
1037 	NO_OP;
1038 }
1039 
1040 /* Copia */
1041 DriveCaller *
pCopy(void) const1042 DirectDriveCaller::pCopy(void) const
1043 {
1044 	DriveCaller* pDC = 0;
1045 	SAFENEWWITHCONSTRUCTOR(pDC,
1046 		DirectDriveCaller,
1047 		DirectDriveCaller(pDrvHdl));
1048 	return pDC;
1049 }
1050 
1051 /* Scrive il contributo del DriveCaller al file di restart */
1052 std::ostream&
Restart(std::ostream & out) const1053 DirectDriveCaller::Restart(std::ostream& out) const
1054 {
1055 	return out << " direct";
1056 }
1057 
1058 /* DirectDriveCaller - end */
1059 
1060 
1061 /* PiecewiseLinearDriveCaller - begin */
1062 
PiecewiseLinearDriveCaller(const DriveHandler * pDH,unsigned int i,doublereal * p)1063 PiecewiseLinearDriveCaller::PiecewiseLinearDriveCaller(const DriveHandler* pDH,
1064 	unsigned int i, doublereal *p)
1065 : DriveCaller(pDH), iNumPoints(i), pPoints(p), pVals(p + i)
1066 {
1067 	ASSERT(i >= 2);
1068 	ASSERT(p != 0);
1069 }
1070 
~PiecewiseLinearDriveCaller(void)1071 PiecewiseLinearDriveCaller::~PiecewiseLinearDriveCaller(void)
1072 {
1073 	if (pPoints != 0) {
1074 		SAFEDELETEARR(pPoints);
1075 	}
1076 }
1077 
1078 /* Copia */
1079 DriveCaller *
pCopy(void) const1080 PiecewiseLinearDriveCaller::pCopy(void) const
1081 {
1082 	doublereal *p = 0;
1083 	SAFENEWARR(p, doublereal, 2*iNumPoints);
1084 	for (unsigned int i = 0; i < 2*iNumPoints; i++) {
1085 		p[i] = pPoints[i];
1086 	}
1087 
1088 	DriveCaller* pDC = 0;
1089 	SAFENEWWITHCONSTRUCTOR(pDC,
1090 			PiecewiseLinearDriveCaller,
1091 			PiecewiseLinearDriveCaller(pDrvHdl, iNumPoints, p));
1092 
1093 	return pDC;
1094 }
1095 
1096 /* Scrive il contributo del DriveCaller al file di restart */
1097 std::ostream&
Restart(std::ostream & out) const1098 PiecewiseLinearDriveCaller::Restart(std::ostream& out) const
1099 {
1100 	out << "piecewise linear, " << iNumPoints;
1101 
1102 	for (unsigned int i = 0; i < iNumPoints; i++) {
1103 		out << ", " << pPoints[i] << ", " << pVals[i];
1104 	}
1105 
1106 	return out;
1107 }
1108 
1109 /* PiecewiseLinearDriveCaller - end */
1110 
1111 
1112 /* DriveArrayCaller - begin */
1113 
DriveArrayCaller(const DriveHandler * pDH,dcv_t & DC)1114 DriveArrayCaller::DriveArrayCaller(const DriveHandler* pDH, dcv_t& DC)
1115 : DriveCaller(pDH), m_dc(DC)
1116 {
1117 #ifdef DEBUG
1118 	ASSERT(!m_dc.empty());
1119 	for (dcv_t::const_iterator i = m_dc.begin(); i != m_dc.end(); ++i) {
1120 		ASSERT((*i) != 0);
1121 	}
1122 #endif /* DEBUG */
1123 }
1124 
~DriveArrayCaller(void)1125 DriveArrayCaller::~DriveArrayCaller(void)
1126 {
1127 	ASSERT(!m_dc.empty());
1128 
1129 	for (dcv_t::iterator i = m_dc.begin(); i != m_dc.end(); ++i) {
1130 		SAFEDELETE(*i);
1131 	}
1132 }
1133 
1134 /* Copia */
1135 DriveCaller *
pCopy(void) const1136 DriveArrayCaller::pCopy(void) const
1137 {
1138 	ASSERT(!m_dc.empty());
1139 
1140 	dcv_t DC(m_dc.size());
1141 
1142 	for (unsigned i = 0; i < m_dc.size(); i++) {
1143 		DC[i] = m_dc[i]->pCopy();
1144 	}
1145 
1146 	DriveCaller* pDC = 0;
1147 	SAFENEWWITHCONSTRUCTOR(pDC,
1148 		DriveArrayCaller,
1149 		DriveArrayCaller(pDrvHdl, DC));
1150 
1151 	return pDC;
1152 }
1153 
1154 /* Scrive il contributo del DriveCaller al file di restart */
1155 std::ostream&
Restart(std::ostream & out) const1156 DriveArrayCaller::Restart(std::ostream& out) const
1157 {
1158 	out << " array, " << m_dc.size();
1159 
1160 	for (dcv_t::const_iterator i = m_dc.begin(); i != m_dc.end(); ++i) {
1161 		ASSERT((*i) != 0);
1162 
1163 		out << ", ", (*i)->Restart(out);
1164 	}
1165 
1166 	return out;
1167 }
1168 
1169 /* DriveArrayCaller - end */
1170 
1171 /* PeriodicDriveCaller - begin */
1172 
PeriodicDriveCaller(const DriveHandler * pDH,const DriveCaller * pDC,doublereal dT0,doublereal dPeriod)1173 PeriodicDriveCaller::PeriodicDriveCaller(const DriveHandler *pDH,
1174 	const DriveCaller* pDC, doublereal dT0, doublereal dPeriod)
1175 : DriveCaller(pDH),
1176 DO(pDC), dT0(dT0), dPeriod(dPeriod)
1177 {
1178 	NO_OP;
1179 }
1180 
~PeriodicDriveCaller(void)1181 PeriodicDriveCaller::~PeriodicDriveCaller(void)
1182 {
1183 	NO_OP;
1184 }
1185 
1186 /* Copia */
1187 DriveCaller *
pCopy(void) const1188 PeriodicDriveCaller::pCopy(void) const
1189 {
1190 	DriveCaller* pDC = 0;
1191 	SAFENEWWITHCONSTRUCTOR(pDC, PeriodicDriveCaller,
1192 		PeriodicDriveCaller(pDrvHdl,
1193 			DO.pGetDriveCaller()->pCopy(), dT0, dPeriod));
1194 	return pDC;
1195 }
1196 
1197 /* Scrive il contributo del DriveCaller al file di restart */
1198 std::ostream&
Restart(std::ostream & out) const1199 PeriodicDriveCaller::Restart(std::ostream& out) const
1200 {
1201 	return out << "periodic, " << dT0 << ", " << dPeriod << ", ",
1202 		DO.pGetDriveCaller()->Restart(out);
1203 }
1204 
1205 /* PeriodicDriveCaller - end */
1206 
1207 /* PostponedDriveCaller - begin */
1208 
1209 void
Check(void) const1210 PostponedDriveCaller::Check(void) const
1211 {
1212 	if (!DO.pGetDriveCaller()) {
1213 		const DriveCaller *pDC = HP.GetDrive(uDriveLabel);
1214 		if (pDC == 0) {
1215 			silent_cerr("PostponedDriveCaller: unable to resolve postponed drive caller \"" << uDriveLabel << "\"" << std::endl);
1216 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
1217 		}
1218 		DO.Set(pDC->pCopy());
1219 		const_cast<PostponedDriveCaller *>(this)->SetDrvHdl(DO.pGetDriveCaller()->pGetDrvHdl());
1220 	}
1221 }
1222 
PostponedDriveCaller(MBDynParser & HP,unsigned uLabel)1223 PostponedDriveCaller::PostponedDriveCaller(MBDynParser& HP, unsigned uLabel)
1224 : DriveCaller(0),
1225 HP(HP), uDriveLabel(uLabel), DO(0)
1226 {
1227 	NO_OP;
1228 }
1229 
~PostponedDriveCaller(void)1230 PostponedDriveCaller::~PostponedDriveCaller(void)
1231 {
1232 	NO_OP;
1233 }
1234 
1235 /* Scrive il contributo del DriveCaller al file di restart */
1236 std::ostream&
Restart(std::ostream & out) const1237 PostponedDriveCaller::Restart(std::ostream& out) const
1238 {
1239 	Check();
1240 
1241 	out << ", deferred, " << uDriveLabel << " /* actual drive: ",
1242 	    DO.pGetDriveCaller()->Restart(out) << " */";
1243 
1244 	return out;
1245 }
1246 
1247 /* Copia */
1248 DriveCaller *
pCopy(void) const1249 PostponedDriveCaller::pCopy(void) const
1250 {
1251 	DriveCaller *pDC = 0;
1252 	SAFENEWWITHCONSTRUCTOR(pDC, PostponedDriveCaller,
1253 		PostponedDriveCaller(HP, uDriveLabel));
1254 	return pDC;
1255 }
1256 
1257 /* PostponedDriveCaller - end */
1258 
1259 
1260 /* bag that contains functions to parse drives */
1261 
1262 typedef std::map<std::string, DriveRead *, ltstrcase> DriveFuncMapType;
1263 static DriveFuncMapType DriveFuncMap;
1264 
1265 struct DriveWordSetType : public HighParser::WordSet {
IsWordDriveWordSetType1266 	bool IsWord(const std::string& s) const {
1267 		return DriveFuncMap.find(s) != DriveFuncMap.end();
1268 	};
1269 };
1270 
1271 static DriveWordSetType DriveWordSet;
1272 
1273 bool
SetDriveData(const std::string & name,DriveRead * rf)1274 SetDriveData(const std::string& name, DriveRead *rf)
1275 {
1276 	pedantic_cout("registering drive \"" << name << "\"" << std::endl);
1277 	return DriveFuncMap.insert(DriveFuncMapType::value_type(name, rf)).second;
1278 }
1279 
1280 /* Reads drives */
1281 
1282 Drive *
ReadDriveData(unsigned uLabel,const DataManager * pDM,MBDynParser & HP)1283 ReadDriveData(unsigned uLabel, const DataManager* pDM, MBDynParser& HP)
1284 {
1285 	DEBUGCOUTFNAME("ReadDriveData()");
1286 
1287 	const char *s = HP.IsWord(DriveWordSet);
1288 	if (s == 0) {
1289 		silent_cerr("ReadDriveData(" << uLabel << "): "
1290 			"unknown drive type "
1291 			"at line " << HP.GetLineData() << std::endl);
1292 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
1293 	}
1294 
1295 	DriveFuncMapType::iterator func = DriveFuncMap.find(std::string(s));
1296 	if (func == DriveFuncMap.end()) {
1297 		silent_cerr("unknown drive type \"" << s << "\" "
1298 			"at line " << HP.GetLineData() << std::endl);
1299 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
1300 	}
1301 
1302 	return func->second->Read(uLabel, pDM, HP);
1303 }
1304 
~DriveRead(void)1305 DriveRead::~DriveRead(void)
1306 {
1307 	NO_OP;
1308 }
1309 
1310 /* bag that contains functions to parse drive callers */
1311 
1312 typedef std::map<std::string, DriveCallerRead *, ltstrcase> DriveCallerFuncMapType;
1313 static DriveCallerFuncMapType DriveCallerFuncMap;
1314 
1315 struct DriveCallerWordSetType : public HighParser::WordSet {
IsWordDriveCallerWordSetType1316 	bool IsWord(const std::string& s) const {
1317 		return DriveCallerFuncMap.find(s) != DriveCallerFuncMap.end();
1318 	};
1319 };
1320 
1321 static DriveCallerWordSetType DriveCallerWordSet;
1322 
1323 bool
SetDriveCallerData(const char * name,DriveCallerRead * rf)1324 SetDriveCallerData(const char *name, DriveCallerRead *rf)
1325 {
1326 	pedantic_cout("registering drive caller \"" << name << "\"" << std::endl);
1327 	return DriveCallerFuncMap.insert(DriveCallerFuncMapType::value_type(name, rf)).second;
1328 }
1329 
1330 /* Reads drive callers */
1331 
1332 DriveCaller *
ReadDriveCallerData(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1333 ReadDriveCallerData(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1334 {
1335 	DEBUGCOUTFNAME("ReadDriveCallerData()");
1336 
1337 	const char *s = HP.IsWord(DriveCallerWordSet);
1338 	if (s == 0) {
1339 		pedantic_cerr("ReadDriveCallerData: warning, assuming \"const\" drive caller at line " << HP.GetLineData() << std::endl);
1340 		s = "const";
1341 	}
1342 
1343 	DriveCallerFuncMapType::iterator func = DriveCallerFuncMap.find(std::string(s));
1344 	if (func == DriveCallerFuncMap.end()) {
1345 		silent_cerr("unknown drive caller type \"" << s << "\" "
1346 			"at line " << HP.GetLineData() << std::endl);
1347 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
1348 	}
1349 
1350 	return func->second->Read(pDM, HP, bDeferred);
1351 }
1352 
1353 void
NeedDM(const DataManager * pDM,MBDynParser & HP,bool bDeferred,const char * const name)1354 DriveCallerRead::NeedDM(const DataManager* pDM, MBDynParser& HP, bool bDeferred,
1355 	const char *const name)
1356 {
1357 	if (pDM == 0 && !bDeferred) {
1358 		silent_cerr("\"" << name << "\" drive caller needs data manager "
1359 			"at line " << HP.GetLineData() << std::endl);
1360 		throw DataManager::ErrNeedDataManager(MBDYN_EXCEPT_ARGS);
1361 	}
1362 }
1363 
~DriveCallerRead(void)1364 DriveCallerRead::~DriveCallerRead(void)
1365 {
1366 	NO_OP;
1367 }
1368 
ReadOutput(DriveCaller * pDC,const DataManager * pDM,MBDynParser & HP)1369 void DriveCallerRead::ReadOutput(DriveCaller* pDC, const DataManager* pDM, MBDynParser& HP)
1370 {
1371 	flag fOutput = pDM->bOutputDriveCallers()
1372 					? DriveCaller::OUTPUT_VALUE
1373 					: 0;
1374 
1375 	if (HP.IsKeyWord("output")) {
1376 		bool bGotKeyWord = false;
1377 
1378 		if (HP.IsKeyWord("value")) {
1379 			bGotKeyWord = true;
1380 
1381 			if (HP.GetYesNoOrBool()) {
1382 				fOutput |= DriveCaller::OUTPUT_VALUE;
1383 			} else {
1384 				fOutput &= ~DriveCaller::OUTPUT_VALUE;
1385        			}
1386 		}
1387 
1388 		if (HP.IsKeyWord("derivative")) {
1389 			bGotKeyWord = true;
1390 
1391 			if (HP.GetYesNoOrBool()) {
1392 				fOutput |= DriveCaller::OUTPUT_DERIVATIVE;
1393 			} else {
1394 				fOutput &= ~DriveCaller::OUTPUT_DERIVATIVE;
1395 			}
1396 		}
1397 
1398 		if (!bGotKeyWord) {
1399 			if (HP.GetYesNoOrBool()) {
1400 				fOutput |= DriveCaller::OUTPUT_VALUE;
1401 
1402 				if (pDC->bIsDifferentiable()) {
1403 					fOutput |= DriveCaller::OUTPUT_DERIVATIVE;
1404 				}
1405 			} else {
1406 				fOutput = flag(0);
1407 			}
1408 		}
1409 	}
1410 
1411 	if (fOutput & DriveCaller::OUTPUT_DERIVATIVE) {
1412 		if (!pDC->bIsDifferentiable()) {
1413 			silent_cerr("warning invalid output flag: drive caller(" << pDC->GetLabel()
1414 					<< ") is not differentiable at line "
1415 					<< HP.GetLineData() << std::endl);
1416 
1417 			fOutput &= ~DriveCaller::OUTPUT_DERIVATIVE;
1418 		}
1419 	}
1420 
1421 	if (fOutput) {
1422 		fOutput |= DriveCaller::OUTPUT;
1423 	}
1424 
1425 	pDC->SetOutputFlag(fOutput);
1426 
1427 	flag fTrace = 0;
1428 
1429 	if (HP.IsKeyWord("output" "trace")) {
1430 		bool bGotKeyWord = false;
1431 
1432 		if (HP.IsKeyWord("value")) {
1433 			bGotKeyWord = true;
1434 
1435 			if (HP.GetYesNoOrBool()) {
1436 				fTrace |= DriveCaller::TRACE_VALUE;
1437        			} else {
1438 				fTrace &= ~DriveCaller::TRACE_VALUE;
1439 			}
1440 		}
1441 
1442 		if (HP.IsKeyWord("derivative")) {
1443 			bGotKeyWord = true;
1444 
1445 			if (HP.GetYesNoOrBool()) {
1446 				fTrace |= DriveCaller::TRACE_DERIVATIVE;
1447 			} else {
1448 				fTrace &= ~DriveCaller::TRACE_DERIVATIVE;
1449 			}
1450 		}
1451 
1452 		if (!bGotKeyWord) {
1453 			if (HP.GetYesNoOrBool()) {
1454 				fTrace |= DriveCaller::TRACE_VALUE;
1455 
1456 				if (pDC->bIsDifferentiable()) {
1457 					fTrace |= DriveCaller::TRACE_DERIVATIVE;
1458 				}
1459 			} else {
1460 				fTrace = flag(0);
1461 			}
1462 		}
1463 	}
1464 
1465 	if (fTrace & DriveCaller::TRACE_DERIVATIVE) {
1466 		if (!pDC->bIsDifferentiable()) {
1467 			silent_cerr("warning invalid trace flag: drive caller (" << pDC->GetLabel()
1468 					<< ") is not differentiable at line "
1469 					<< HP.GetLineData() << std::endl);
1470 
1471 			fTrace &= ~DriveCaller::TRACE_DERIVATIVE;
1472 		}
1473 	}
1474 
1475 	if (fTrace) {
1476 		fTrace |= DriveCaller::TRACE;
1477 	}
1478 
1479 	pDC->SetTraceFlag(fTrace);
1480 }
1481 
1482 struct TimeDCR : public DriveCallerRead {
1483 	DriveCaller *
1484 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1485 };
1486 
1487 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1488 TimeDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1489 {
1490 	NeedDM(pDM, HP, bDeferred, "time");
1491 
1492 	const DriveHandler* pDrvHdl = 0;
1493 	if (pDM != 0) {
1494 		pDrvHdl = pDM->pGetDrvHdl();
1495 	}
1496 
1497 	DriveCaller *pDC = 0;
1498 
1499 	SAFENEWWITHCONSTRUCTOR(pDC, TimeDriveCaller, TimeDriveCaller(pDrvHdl));
1500 
1501 	return pDC;
1502 }
1503 
1504 struct TimeStepDCR : public DriveCallerRead {
1505 	DriveCaller *
1506 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1507 };
1508 
1509 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1510 TimeStepDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1511 {
1512 	NeedDM(pDM, HP, bDeferred, "timestep");
1513 
1514 	const DriveHandler* pDrvHdl = 0;
1515 	if (pDM != 0) {
1516 		pDrvHdl = pDM->pGetDrvHdl();
1517 	}
1518 
1519 	DriveCaller *pDC = 0;
1520 
1521 	SAFENEWWITHCONSTRUCTOR(pDC, TimeStepDriveCaller, TimeStepDriveCaller(pDrvHdl));
1522 
1523 	return pDC;
1524 }
1525 
1526 struct MultDCR : public DriveCallerRead {
1527 	DriveCaller *
1528 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1529 };
1530 
1531 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1532 MultDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1533 {
1534 	NeedDM(pDM, HP, bDeferred, "mult");
1535 
1536 	const DriveHandler* pDrvHdl = 0;
1537 	if (pDM != 0) {
1538 		pDrvHdl = pDM->pGetDrvHdl();
1539 	}
1540 
1541 	DriveCaller* pDC1 = HP.GetDriveCaller();
1542 	DriveCaller* pDC2 = HP.GetDriveCaller();
1543 
1544 	DriveCaller *pDC = 0;
1545 	SAFENEWWITHCONSTRUCTOR(pDC,
1546 		MultDriveCaller,
1547 		MultDriveCaller(pDrvHdl, pDC1, pDC2));
1548 
1549 	return pDC;
1550 }
1551 
1552 struct NullDCR : public DriveCallerRead {
1553 	DriveCaller *
1554 	Read(const DataManager* /* pDM */ , MBDynParser& /* HP */ , bool /* bDeferred */ );
1555 };
1556 
1557 DriveCaller *
Read(const DataManager *,MBDynParser &,bool)1558 NullDCR::Read(const DataManager* /* pDM */ , MBDynParser& /* HP */ , bool /* bDeferred */ )
1559 {
1560 	DriveCaller *pDC = 0;
1561 
1562         SAFENEW(pDC, NullDriveCaller);
1563 
1564 	return pDC;
1565 }
1566 
1567 struct OneDCR : public DriveCallerRead {
1568 	DriveCaller *
1569 	Read(const DataManager* /* pDM */ , MBDynParser& /* HP */ , bool /* bDeferred */ );
1570 };
1571 
1572 DriveCaller *
Read(const DataManager *,MBDynParser &,bool)1573 OneDCR::Read(const DataManager* /* pDM */ , MBDynParser& /* HP */ , bool /* bDeferred */ )
1574 {
1575 	DriveCaller *pDC = 0;
1576 
1577         SAFENEW(pDC, OneDriveCaller);
1578 
1579 	return pDC;
1580 }
1581 
1582 struct ConstDCR : public DriveCallerRead {
1583 	DriveCaller *
1584 	Read(const DataManager* pDM, MBDynParser& HP, bool /* bDeferred */ );
1585 };
1586 
1587 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool)1588 ConstDCR::Read(const DataManager* pDM, MBDynParser& HP, bool /* bDeferred */ )
1589 {
1590 	DriveCaller *pDC = 0;
1591 
1592 	/* lettura dei dati specifici */
1593 	doublereal dConst = HP.GetReal();
1594 	DEBUGCOUT("Const value: " << dConst << std::endl);
1595 
1596 	/* allocazione e creazione */
1597 	if (dConst == 0.) {
1598 		SAFENEW(pDC, NullDriveCaller);
1599 
1600 	} else if (dConst == 1.) {
1601 		SAFENEW(pDC, OneDriveCaller);
1602 
1603 	} else {
1604 		SAFENEWWITHCONSTRUCTOR(pDC, ConstDriveCaller, ConstDriveCaller(dConst));
1605 	}
1606 
1607 	return pDC;
1608 }
1609 
1610 struct LinearDCR : public DriveCallerRead {
1611 	DriveCaller *
1612 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1613 };
1614 
1615 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1616 LinearDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1617 {
1618 	NeedDM(pDM, HP, bDeferred, "linear");
1619 
1620 	const DriveHandler* pDrvHdl = 0;
1621 	if (pDM != 0) {
1622 		pDrvHdl = pDM->pGetDrvHdl();
1623 	}
1624 
1625 	DriveCaller *pDC = 0;
1626 
1627 	/* lettura dei dati specifici */
1628 	doublereal dC0 = HP.GetReal();
1629 	DEBUGCOUT("Offset: " << dC0 << std::endl);
1630 
1631 	doublereal dC1 = HP.GetReal();
1632 	DEBUGCOUT("Slope: " << dC1 << std::endl);
1633 
1634 	/* allocazione e creazione */
1635 	SAFENEWWITHCONSTRUCTOR(pDC,
1636 		LinearDriveCaller,
1637 		LinearDriveCaller(pDrvHdl, dC0, dC1));
1638 
1639 	return pDC;
1640 }
1641 
1642 struct ParabolicDCR : public DriveCallerRead {
1643 	DriveCaller *
1644 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1645 };
1646 
1647 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1648 ParabolicDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1649 {
1650 	NeedDM(pDM, HP, bDeferred, "parabolic");
1651 
1652 	const DriveHandler* pDrvHdl = 0;
1653 	if (pDM != 0) {
1654 		pDrvHdl = pDM->pGetDrvHdl();
1655 	}
1656 
1657 	DriveCaller *pDC = 0;
1658 
1659 	/* lettura dei dati specifici */
1660 	doublereal dC0 = HP.GetReal();
1661 	DEBUGCOUT("Offset: " << dC0 << std::endl);
1662 
1663 	doublereal dC1 = HP.GetReal();
1664 	DEBUGCOUT("Slope: " << dC1 << std::endl);
1665 
1666 	doublereal dC2 = HP.GetReal();
1667 	DEBUGCOUT("Parabolic slope: " << dC2 << std::endl);
1668 
1669 	/* allocazione e creazione */
1670 	SAFENEWWITHCONSTRUCTOR(pDC,
1671 		ParabolicDriveCaller,
1672 		ParabolicDriveCaller(pDrvHdl, dC0, dC1, dC2));
1673 
1674 	return pDC;
1675 }
1676 
1677 struct CubicDCR : public DriveCallerRead {
1678 	DriveCaller *
1679 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1680 };
1681 
1682 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1683 CubicDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1684 {
1685 	NeedDM(pDM, HP, bDeferred, "cubic");
1686 
1687 	const DriveHandler* pDrvHdl = 0;
1688 	if (pDM != 0) {
1689 		pDrvHdl = pDM->pGetDrvHdl();
1690 	}
1691 
1692 	DriveCaller *pDC = 0;
1693 
1694 	/* lettura dei dati specifici */
1695 	doublereal dC0 = HP.GetReal();
1696 	DEBUGCOUT("Offset: " << dC0 << std::endl);
1697 
1698 	doublereal dC1 = HP.GetReal();
1699 	DEBUGCOUT("Slope: " << dC1 << std::endl);
1700 
1701 	doublereal dC2 = HP.GetReal();
1702 	DEBUGCOUT("Parabolic slope: " << dC2 << std::endl);
1703 
1704 	doublereal dC3 = HP.GetReal();
1705 	DEBUGCOUT("Cubic slope: " << dC3 << std::endl);
1706 
1707 	/* allocazione e creazione */
1708 	SAFENEWWITHCONSTRUCTOR(pDC,
1709 		CubicDriveCaller,
1710 		CubicDriveCaller(pDrvHdl, dC0, dC1, dC2, dC3));
1711 
1712 	return pDC;
1713 }
1714 
1715 /*
1716  * this allows each drive to be preceded by the keyword "function"
1717  */
1718 struct FunctionDCR : public DriveCallerRead {
1719 	DriveCaller *
1720 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1721 };
1722 
1723 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1724 FunctionDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1725 {
1726 	return HP.GetDriveCaller(bDeferred);
1727 }
1728 
1729 struct StepDCR : public DriveCallerRead {
1730 	DriveCaller *
1731 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1732 };
1733 
1734 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1735 StepDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1736 {
1737 	NeedDM(pDM, HP, bDeferred, "step");
1738 
1739 	const DriveHandler* pDrvHdl = 0;
1740 	if (pDM != 0) {
1741 		pDrvHdl = pDM->pGetDrvHdl();
1742 	}
1743 
1744 	DriveCaller *pDC = 0;
1745 
1746 	doublereal dStepTime = HP.GetReal();
1747 	DEBUGCOUT("Initial time: " << dStepTime << std::endl);
1748 
1749 	doublereal dStepValue = HP.GetReal(1.);
1750 	DEBUGCOUT("Step Value: " << dStepValue << std::endl);
1751 
1752 	doublereal dInitialValue = HP.GetReal();
1753 	DEBUGCOUT("InitialValue: " << dInitialValue << std::endl);
1754 
1755 	SAFENEWWITHCONSTRUCTOR(pDC,
1756 		StepDriveCaller,
1757 		StepDriveCaller(pDrvHdl, dStepTime, dStepValue, dInitialValue));
1758 
1759 	return pDC;
1760 }
1761 
1762 struct DoubleStepDCR : public DriveCallerRead {
1763 	DriveCaller *
1764 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1765 };
1766 
1767 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1768 DoubleStepDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1769 {
1770 	NeedDM(pDM, HP, bDeferred, "double step");
1771 
1772 	const DriveHandler* pDrvHdl = 0;
1773 	if (pDM != 0) {
1774 		pDrvHdl = pDM->pGetDrvHdl();
1775 	}
1776 
1777 	DriveCaller *pDC = 0;
1778 
1779 	doublereal dStepTime = HP.GetReal();
1780 	DEBUGCOUT("Initial time: " << dStepTime << std::endl);
1781 
1782 	doublereal dEndStepTime = HP.GetReal();
1783 	DEBUGCOUT("Final time: " << dEndStepTime << std::endl);
1784 
1785 	if (dEndStepTime <= dStepTime) {
1786 		silent_cerr("Warning at line "
1787 			<< HP.GetLineData()
1788 			<< ": final time " << dEndStepTime
1789 			<< " is less than or equal to initial time " << dStepTime
1790 			<< " in double step func drive" << std::endl);
1791 	}
1792 
1793 	doublereal dStepValue = HP.GetReal(1.);
1794 	DEBUGCOUT("Step Value: " << dStepValue << std::endl);
1795 
1796 	doublereal dInitialValue = HP.GetReal();
1797 	DEBUGCOUT("InitialValue: " << dInitialValue << std::endl);
1798 
1799 	SAFENEWWITHCONSTRUCTOR(pDC,
1800 		DoubleStepDriveCaller,
1801 		DoubleStepDriveCaller(pDrvHdl,
1802 			dStepTime,
1803 			dStepValue,
1804 			dEndStepTime,
1805 			dInitialValue));
1806 
1807 	return pDC;
1808 }
1809 
1810 struct RampDCR : public DriveCallerRead {
1811 	DriveCaller *
1812 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1813 };
1814 
1815 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1816 RampDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1817 {
1818 	NeedDM(pDM, HP, bDeferred, "ramp");
1819 
1820 	const DriveHandler* pDrvHdl = 0;
1821 	if (pDM != 0) {
1822 		pDrvHdl = pDM->pGetDrvHdl();
1823 	}
1824 
1825 	DriveCaller *pDC = 0;
1826 
1827 	/* Rampa saturata */
1828 	doublereal dSlope = HP.GetReal(1.);
1829 	DEBUGCOUT("Slope Value: " << dSlope << std::endl);
1830 
1831 	doublereal dInitialTime = HP.GetReal();
1832 	DEBUGCOUT("Initial time: " << dInitialTime << std::endl);
1833 
1834 	doublereal dFinalTime = std::numeric_limits<double>::max();
1835 	if (!HP.IsKeyWord("forever")) {
1836 		dFinalTime = HP.GetReal();
1837 	}
1838 	DEBUGCOUT("Final time: " << dFinalTime << std::endl);
1839 
1840 	if (dFinalTime <= dInitialTime) {
1841 		silent_cerr("Warning at line "
1842 			<< HP.GetLineData()
1843 			<< ": final time " << dFinalTime
1844 			<< " is less than or equal to initial time " << dInitialTime
1845 			<< " in ramp func drive" << std::endl);
1846 	}
1847 
1848 	doublereal dInitialValue = HP.GetReal();
1849 	DEBUGCOUT("InitialValue: " << dInitialValue << std::endl);
1850 
1851 	SAFENEWWITHCONSTRUCTOR(pDC,
1852 		RampDriveCaller,
1853 		RampDriveCaller(pDrvHdl, dSlope, dInitialTime,
1854 			dFinalTime, dInitialValue));
1855 
1856 	return pDC;
1857 }
1858 
1859 struct DoubleRampDCR : public DriveCallerRead {
1860 	DriveCaller *
1861 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
1862 };
1863 
1864 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)1865 DoubleRampDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
1866 {
1867 	NeedDM(pDM, HP, bDeferred, "double ramp");
1868 
1869 	const DriveHandler* pDrvHdl = 0;
1870 	if (pDM != 0) {
1871 		pDrvHdl = pDM->pGetDrvHdl();
1872 	}
1873 
1874 	DriveCaller *pDC = 0;
1875 
1876 	/* Rampa doppia */
1877 	doublereal dAscendingSlope = HP.GetReal(1.);
1878 	DEBUGCOUT("Ascending Slope Value: " << dAscendingSlope << std::endl);
1879 
1880 	doublereal dAscendingInitialTime = HP.GetReal();
1881 	DEBUGCOUT("Ascending Initial time: " << dAscendingInitialTime << std::endl);
1882 
1883 	doublereal dAscendingFinalTime = HP.GetReal();
1884 	DEBUGCOUT("Ascending Final time: " << dAscendingFinalTime << std::endl);
1885 
1886 	if (dAscendingFinalTime <= dAscendingInitialTime) {
1887 		silent_cerr("Warning at line "
1888 			<< HP.GetLineData() << ": ascending final time "
1889 			<< dAscendingFinalTime
1890 			<< " is less than or equal to ascending initial time "
1891 			<< dAscendingInitialTime
1892 			<< " in double ramp func drive" << std::endl);
1893 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
1894 	}
1895 
1896 	doublereal dDescendingSlope = HP.GetReal(-1.);
1897 	DEBUGCOUT("Descending Slope Value: " << dDescendingSlope << std::endl);
1898 
1899 	doublereal dDescendingInitialTime = std::numeric_limits<doublereal>::max();
1900 	if (!HP.IsKeyWord("forever")) {
1901 		dDescendingInitialTime = HP.GetReal();
1902 	}
1903 	DEBUGCOUT("Descending Initial time: " << dDescendingInitialTime << std::endl);
1904 
1905 	if (dDescendingInitialTime < dAscendingFinalTime) {
1906 		silent_cerr("Warning at line "
1907 			<< HP.GetLineData() << ": descending initial time "
1908 			<< dDescendingInitialTime
1909 			<< " is less than ascending final time "
1910 			<< dAscendingFinalTime
1911 			<< " in double ramp func drive" << std::endl);
1912 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
1913 	}
1914 
1915 	doublereal dDescendingFinalTime;
1916 	if (HP.IsKeyWord("forever")) {
1917 		dDescendingFinalTime = std::numeric_limits<doublereal>::max();
1918 
1919 	} else {
1920 		dDescendingFinalTime = HP.GetReal();
1921 	}
1922 
1923 	DEBUGCOUT("Descending Final time: " << dDescendingFinalTime << std::endl);
1924 
1925 	if (dDescendingFinalTime <= dDescendingInitialTime) {
1926 		silent_cerr("Warning at line "
1927 			<< HP.GetLineData() << ": descending final time "
1928 			<< dDescendingFinalTime
1929 			<< " is less than descending initial time "
1930 			<< dDescendingInitialTime
1931 			<< " in double ramp func drive" << std::endl);
1932 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
1933 	}
1934 
1935 	doublereal dInitialValue = HP.GetReal();
1936 	DEBUGCOUT("InitialValue: " << dInitialValue << std::endl);
1937 
1938 	SAFENEWWITHCONSTRUCTOR(pDC,
1939 		DoubleRampDriveCaller,
1940 		DoubleRampDriveCaller(pDrvHdl,
1941 			dAscendingSlope, dAscendingInitialTime, dAscendingFinalTime,
1942 			dDescendingSlope, dDescendingInitialTime, dDescendingFinalTime,
1943 			dInitialValue));
1944 
1945 	return pDC;
1946 }
1947 
1948 struct SineCosineDCR {
1949 protected:
~SineCosineDCRSineCosineDCR1950 	virtual ~SineCosineDCR(void) { NO_OP; };
1951 	virtual DriveCaller *
1952 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred, bool bSine);
1953 };
1954 
1955 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred,bool bSine)1956 SineCosineDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred, bool bSine)
1957 {
1958 	const DriveHandler* pDrvHdl = 0;
1959 	if (pDM != 0) {
1960 		pDrvHdl = pDM->pGetDrvHdl();
1961 	}
1962 
1963 	DriveCaller *pDC = 0;
1964 
1965 	/* Seno e coseno (limitati, illimitati, saturati) */
1966 	doublereal dInitialTime = HP.GetReal();
1967 	DEBUGCOUT("Initial time: " << dInitialTime << std::endl);
1968 
1969 	doublereal dOmega = HP.GetReal(1.);
1970 	DEBUGCOUT("Omega: " << dOmega << std::endl);
1971 
1972 	doublereal dAmplitude = HP.GetReal();
1973 	DEBUGCOUT("Amplitude: " << dAmplitude << std::endl);
1974 
1975 	integer iNumCycles;
1976 	if (HP.IsKeyWord("forever")) {
1977 		iNumCycles = 0;
1978 
1979 	} else if (HP.IsKeyWord("one")) {
1980 		iNumCycles = 1;
1981 
1982 	} else if (HP.IsKeyWord("half")) {
1983 		iNumCycles = -1;
1984 
1985 	} else {
1986 		iNumCycles = HP.GetInt();
1987 	}
1988 	DEBUGCOUT("Number of cycles: " << iNumCycles << std::endl);
1989 
1990 	doublereal dInitialValue = HP.GetReal();
1991 	DEBUGCOUT("InitialValue: " << dInitialValue << std::endl);
1992 
1993 	if (bSine) {
1994 		SAFENEWWITHCONSTRUCTOR(pDC,
1995 			SineDriveCaller,
1996 			SineDriveCaller(pDrvHdl, dInitialTime, dOmega, dAmplitude, iNumCycles, dInitialValue));
1997 
1998 	} else {
1999 		SAFENEWWITHCONSTRUCTOR(pDC,
2000 			CosineDriveCaller,
2001 			CosineDriveCaller(pDrvHdl, dInitialTime, dOmega, dAmplitude, iNumCycles, dInitialValue));
2002 	}
2003 
2004 	return pDC;
2005 }
2006 
2007 struct SineDCR : public DriveCallerRead, protected SineCosineDCR {
2008 	DriveCaller *
2009 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2010 };
2011 
2012 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2013 SineDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2014 {
2015 	NeedDM(pDM, HP, bDeferred, "sine");
2016 
2017 	return SineCosineDCR::Read(pDM, HP, bDeferred, true);
2018 }
2019 
2020 struct CosineDCR : public DriveCallerRead, protected SineCosineDCR {
2021 	DriveCaller *
2022 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2023 };
2024 
2025 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2026 CosineDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2027 {
2028 	NeedDM(pDM, HP, bDeferred, "cosine");
2029 
2030 	return SineCosineDCR::Read(pDM, HP, bDeferred, false);
2031 }
2032 
2033 struct TanhDCR : public DriveCallerRead {
2034 	virtual DriveCaller *
2035 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2036 };
2037 
2038 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2039 TanhDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2040 {
2041 	NeedDM(pDM, HP, bDeferred, "tanh");
2042 
2043 	const DriveHandler* pDrvHdl = 0;
2044 	if (pDM != 0) {
2045 		pDrvHdl = pDM->pGetDrvHdl();
2046 	}
2047 
2048 	DriveCaller *pDC = 0;
2049 
2050 	/* Seno e coseno (limitati, illimitati, saturati) */
2051 	doublereal dStart = HP.GetReal();
2052 	DEBUGCOUT("Initial time: " << dStart << std::endl);
2053 
2054 	doublereal dA = HP.GetReal(1.);
2055 	DEBUGCOUT("Amplitude: " << dA << std::endl);
2056 
2057 	doublereal dB = HP.GetReal();
2058 	DEBUGCOUT("Slope: " << dB << std::endl);
2059 
2060 	doublereal dInitialValue = HP.GetReal();
2061 	DEBUGCOUT("InitialValue: " << dInitialValue << std::endl);
2062 
2063 	SAFENEWWITHCONSTRUCTOR(pDC,
2064 		TanhDriveCaller,
2065 		TanhDriveCaller(pDrvHdl, dStart, dA, dB, dInitialValue));
2066 
2067 	return pDC;
2068 }
2069 
2070 struct FourierSeriesDCR : public DriveCallerRead {
2071 	DriveCaller *
2072 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2073 };
2074 
2075 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2076 FourierSeriesDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2077 {
2078 	NeedDM(pDM, HP, bDeferred, "Fourier series");
2079 
2080 	const DriveHandler* pDrvHdl = 0;
2081 	if (pDM != 0) {
2082 		pDrvHdl = pDM->pGetDrvHdl();
2083 	}
2084 
2085 	DriveCaller *pDC = 0;
2086 
2087 	doublereal dInitialTime = HP.GetReal();
2088 	DEBUGCOUT("Initial time: " << dInitialTime << std::endl);
2089 
2090 	doublereal dOmega = HP.GetReal(1.);
2091 	DEBUGCOUT("Omega: " << dOmega << std::endl);
2092 
2093 	int n = HP.GetInt();
2094 	if (n <= 0) {
2095 		silent_cerr("FourierSeriesDriveCaller: invalid order " << n
2096 			<< " at line " << HP.GetLineData() << std::endl);
2097 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2098 	}
2099 
2100 	std::vector<doublereal> a(1 + 2*n);
2101 	for (unsigned i = 0; i < 1 + 2*unsigned(n); i++) {
2102 		a[i] = HP.GetReal();
2103 	}
2104 
2105 	/* don't remember why, but the series starts with a_0/2 */
2106 	a[0] /= 2.;
2107 
2108 	integer iNumCycles;
2109 	if (HP.IsKeyWord("forever")) {
2110 		iNumCycles = 0;
2111 
2112 	} else if (HP.IsKeyWord("one")) {
2113 		iNumCycles = 1;
2114 
2115 	} else {
2116 		iNumCycles = HP.GetInt();
2117 	}
2118 	DEBUGCOUT("Number of cycles: " << iNumCycles << std::endl);
2119 	if (iNumCycles < 0) {
2120 		silent_cerr("FourierSeriesDriveCaller: invalid number of cycles "
2121 			<< iNumCycles << " at line " << HP.GetLineData() << std::endl);
2122 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2123 	}
2124 
2125 	doublereal dInitialValue = HP.GetReal();
2126 	DEBUGCOUT("InitialValue: " << dInitialValue << std::endl);
2127 
2128 	SAFENEWWITHCONSTRUCTOR(pDC,
2129 		FourierSeriesDriveCaller,
2130 		FourierSeriesDriveCaller(pDrvHdl,
2131 			dInitialTime,
2132 			dOmega,
2133 			a,
2134 			iNumCycles,
2135 			dInitialValue));
2136 
2137 	return pDC;
2138 }
2139 
2140 struct FrequencySweepDCR : public DriveCallerRead {
2141 	DriveCaller *
2142 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2143 };
2144 
2145 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2146 FrequencySweepDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2147 {
2148 	NeedDM(pDM, HP, bDeferred, "frequency sweep");
2149 
2150 	const DriveHandler* pDrvHdl = 0;
2151 	if (pDM != 0) {
2152 		pDrvHdl = pDM->pGetDrvHdl();
2153 	}
2154 
2155 	DriveCaller *pDC = 0;
2156 
2157 	doublereal dInitialTime = HP.GetReal();
2158 	DEBUGCOUT("Initial time: " << dInitialTime << std::endl);
2159 
2160 	DriveCaller* pOmega = 0;
2161 	pOmega = HP.GetDriveCaller();
2162 
2163 	DriveCaller* pAmplitude = 0;
2164 	pAmplitude = HP.GetDriveCaller();
2165 
2166 	doublereal dInitialValue = HP.GetReal();
2167 	DEBUGCOUT("Initial value: " << dInitialValue << std::endl);
2168 
2169 	doublereal dFinalTime = std::numeric_limits<double>::max();
2170 	if (!HP.IsKeyWord("forever")) {
2171 		dFinalTime = HP.GetReal();
2172 	}
2173 	DEBUGCOUT("Final time: " << dFinalTime << std::endl);
2174 
2175 	doublereal dFinalValue = HP.GetReal();
2176 	DEBUGCOUT("Final value: " << dFinalValue << std::endl);
2177 
2178 	SAFENEWWITHCONSTRUCTOR(pDC,
2179 		FreqSweepDriveCaller,
2180 		FreqSweepDriveCaller(pDrvHdl, dInitialTime, pOmega, pAmplitude,
2181 			dInitialValue, dFinalTime, dFinalValue));
2182 
2183 	return pDC;
2184 }
2185 
2186 struct ExponentialDCR : public DriveCallerRead {
2187 	DriveCaller *
2188 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2189 };
2190 
2191 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2192 ExponentialDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2193 {
2194 	NeedDM(pDM, HP, bDeferred, "exponential");
2195 
2196 	const DriveHandler* pDrvHdl = 0;
2197 	if (pDM != 0) {
2198 		pDrvHdl = pDM->pGetDrvHdl();
2199 	}
2200 
2201 	DriveCaller *pDC = 0;
2202 
2203 	doublereal dAmplitude = HP.GetReal(1.);
2204 	DEBUGCOUT("Amplitude value: " << dAmplitude << std::endl);
2205 
2206 	doublereal dTimeConst = HP.GetReal();
2207 	DEBUGCOUT("Time constant value: " << dTimeConst << std::endl);
2208 
2209 	doublereal dInitialTime = HP.GetReal();
2210 	DEBUGCOUT("Initial time: " << dInitialTime << std::endl);
2211 
2212 	doublereal dInitialValue = HP.GetReal();
2213 	DEBUGCOUT("Initial value: " << dInitialValue << std::endl);
2214 
2215 	SAFENEWWITHCONSTRUCTOR(pDC,
2216 		ExpDriveCaller,
2217 		ExpDriveCaller(pDrvHdl, dAmplitude, dTimeConst,
2218 			dInitialTime, dInitialValue));
2219 
2220 	return pDC;
2221 }
2222 
2223 struct RandomDCR : public DriveCallerRead {
2224 	DriveCaller *
2225 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2226 };
2227 
2228 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2229 RandomDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2230 {
2231 	NeedDM(pDM, HP, bDeferred, "random");
2232 
2233 	const DriveHandler* pDrvHdl = 0;
2234 	if (pDM != 0) {
2235 		pDrvHdl = pDM->pGetDrvHdl();
2236 	}
2237 
2238 	DriveCaller *pDC = 0;
2239 
2240 	/* Numero casuale */
2241 	doublereal dAmplitude = HP.GetReal(1.);
2242 	DEBUGCOUT("Amplitude value: " << dAmplitude << std::endl);
2243 
2244 	doublereal dRefVal = HP.GetReal();
2245 	DEBUGCOUT("Mean value: " << dRefVal << std::endl);
2246 
2247 	doublereal dInitialTime = HP.GetReal();
2248 	DEBUGCOUT("Initial time: " << dInitialTime << std::endl);
2249 
2250 	doublereal dFinalTime = std::numeric_limits<double>::max();
2251 	if (!HP.IsKeyWord("forever")) {
2252 		dFinalTime = HP.GetReal();
2253 	}
2254 	DEBUGCOUT("Final time: " << dFinalTime << std::endl);
2255 
2256 	/* Type of random number (additional data) */
2257 	integer iSteps = 1;
2258 	while (true) {
2259 		if (HP.IsKeyWord("steps")) {
2260 			iSteps = HP.GetInt();
2261 			if (iSteps <= 0) {
2262 				silent_cerr("Warning: Steps number " << iSteps
2263 					<< " is illegal; resorting to default value" << std::endl);
2264 				iSteps = 1;
2265 			}
2266 			DEBUGCOUT("Force changes every " << iSteps
2267 				<< " steps" << std::endl);
2268 
2269 		} else if (HP.IsKeyWord("seed")) {
2270 			if (HP.IsKeyWord("time")) {
2271 				DEBUGCOUT("(Re)Seeding random numbers with current time ...");
2272 				srand(time(0));
2273 			} else {
2274 				DEBUGCOUT("(Re)Seeding random numbers with given value ...");
2275 				srand(HP.GetInt());
2276 			}
2277 		} else {
2278 			break;
2279 		}
2280 	}
2281 
2282 	SAFENEWWITHCONSTRUCTOR(pDC,
2283 		RandDriveCaller,
2284 		RandDriveCaller(pDrvHdl, dAmplitude, dRefVal, dInitialTime, dFinalTime, iSteps));
2285 
2286 	return pDC;
2287 }
2288 
2289 struct MeterDCR : public DriveCallerRead {
2290 	DriveCaller *
2291 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2292 };
2293 
2294 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2295 MeterDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2296 {
2297 	NeedDM(pDM, HP, bDeferred, "meter");
2298 
2299 	const DriveHandler* pDrvHdl = 0;
2300 	if (pDM != 0) {
2301 		pDrvHdl = pDM->pGetDrvHdl();
2302 	}
2303 
2304 	DriveCaller *pDC = 0;
2305 
2306 	/* spike every N steps */
2307 	doublereal dInitialTime = HP.GetReal();
2308 	DEBUGCOUT("Initial time: " << dInitialTime << std::endl);
2309 
2310 	doublereal dFinalTime = std::numeric_limits<double>::max();
2311 	if (!HP.IsKeyWord("forever")) {
2312 		dFinalTime = HP.GetReal();
2313 	}
2314 	DEBUGCOUT("Final time: " << dFinalTime << std::endl);
2315 
2316 	/* Type of random number (additional data) */
2317 	integer iSteps = 1;
2318 	while (true) {
2319 		if (HP.IsKeyWord("steps")) {
2320 			iSteps = HP.GetInt();
2321 			if (iSteps <= 0) {
2322 				silent_cerr("Warning: Steps number " << iSteps
2323 					<< " is illegal; resorting to default value" << std::endl);
2324 				iSteps = 1;
2325 			}
2326 			DEBUGCOUT("Force changes every " << iSteps
2327 				<< " steps" << std::endl);
2328 		} else {
2329 			break;
2330 		}
2331 	}
2332 
2333 	SAFENEWWITHCONSTRUCTOR(pDC,
2334 		MeterDriveCaller,
2335 		MeterDriveCaller(pDrvHdl, dInitialTime, dFinalTime, iSteps));
2336 
2337 	return pDC;
2338 }
2339 
2340 struct ClosestNextDCR : public DriveCallerRead {
2341 	DriveCaller *
2342 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2343 };
2344 
2345 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2346 ClosestNextDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2347 {
2348 	NeedDM(pDM, HP, bDeferred, "closest next");
2349 
2350 	const DriveHandler* pDrvHdl = 0;
2351 	if (pDM != 0) {
2352 		pDrvHdl = pDM->pGetDrvHdl();
2353 	}
2354 
2355 	DriveCaller *pDC = 0;
2356 
2357 	doublereal dInitialTime = HP.GetReal();
2358 	DEBUGCOUT("Initial time: " << dInitialTime << std::endl);
2359 
2360 	doublereal dFinalTime = std::numeric_limits<double>::max();
2361 	if (!HP.IsKeyWord("forever")) {
2362 		dFinalTime = HP.GetReal();
2363 	}
2364 	DEBUGCOUT("Final time: " << dFinalTime << std::endl);
2365 
2366 	const DriveCaller *pIncrement = HP.GetDriveCaller(bDeferred);
2367 
2368 	SAFENEWWITHCONSTRUCTOR(pDC,
2369 		ClosestNextDriveCaller,
2370 		ClosestNextDriveCaller(pDrvHdl, dInitialTime, dFinalTime,
2371 			pIncrement));
2372 
2373 	return pDC;
2374 }
2375 
2376 struct DirectDCR : public DriveCallerRead {
2377 	DriveCaller *
2378 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2379 };
2380 
2381 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2382 DirectDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2383 {
2384 	NeedDM(pDM, HP, bDeferred, "direct");
2385 
2386 	const DriveHandler* pDrvHdl = 0;
2387 	if (pDM != 0) {
2388 		pDrvHdl = pDM->pGetDrvHdl();
2389 	}
2390 
2391 	DriveCaller *pDC = 0;
2392 
2393 	SAFENEWWITHCONSTRUCTOR(pDC,
2394 		DirectDriveCaller,
2395 		DirectDriveCaller(pDrvHdl));
2396 
2397 	return pDC;
2398 }
2399 
2400 struct PiecewiseLinearDCR : public DriveCallerRead {
2401 	DriveCaller *
2402 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2403 };
2404 
2405 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2406 PiecewiseLinearDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2407 {
2408 	NeedDM(pDM, HP, bDeferred, "piecewise linear");
2409 
2410 	const DriveHandler* pDrvHdl = 0;
2411 	if (pDM != 0) {
2412 		pDrvHdl = pDM->pGetDrvHdl();
2413 	}
2414 
2415 	DriveCaller *pDC = 0;
2416 
2417 	/* Lineare a pezzi */
2418 	unsigned int n = HP.GetInt();
2419 	DEBUGCOUT("number of points: " << n << std::endl);
2420 
2421 	if (n < 2) {
2422 		silent_cerr("Need at least two points for piecewise linear drive at line "
2423 			<< HP.GetLineData() << std::endl);
2424 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2425 	}
2426 
2427 	doublereal *p = 0;
2428 	SAFENEWARR(p, doublereal, 2*n);
2429 	p[0] = HP.GetReal();
2430 	p[n] = HP.GetReal();
2431 	for (unsigned int i = 1; i < n; i++) {
2432 		p[i] = HP.GetReal();
2433 		if (p[i] <= p[i-1]) {
2434 			silent_cerr("point " << p[i]
2435 				<< " is smaller than or equal to preceding point " << p[i-1]
2436 				<< " at line " << HP.GetLineData() << std::endl);
2437 			SAFEDELETE(p);
2438 			throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2439 		}
2440 		p[i+n] = HP.GetReal();
2441 	}
2442 
2443 	/* allocazione e creazione */
2444 	SAFENEWWITHCONSTRUCTOR(pDC,
2445 		PiecewiseLinearDriveCaller,
2446 		PiecewiseLinearDriveCaller(pDrvHdl, n, p));
2447 
2448 	return pDC;
2449 }
2450 
2451 struct StringDCR : public DriveCallerRead {
2452 	DriveCaller *
2453 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2454 };
2455 
2456 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2457 StringDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2458 {
2459 	NeedDM(pDM, HP, bDeferred, "string");
2460 
2461 	const DriveHandler* pDrvHdl = 0;
2462 	if (pDM != 0) {
2463 		pDrvHdl = pDM->pGetDrvHdl();
2464 	}
2465 
2466 	DriveCaller *pDC = 0;
2467 
2468 	/* driver stringa da valutare */
2469 	/* lettura dei dati specifici */
2470 	std::string s(HP.GetStringWithDelims());
2471 
2472 #ifdef USE_EE
2473 	std::istringstream in(s);
2474 	InputStream In(in);
2475 
2476 	ExpressionElement *expr = HP.GetMathParser().GetExpr(In);
2477 
2478 	if (pedantic_out) {
2479 		std::string out = EEStrOut(expr);
2480 		pedantic_cout("StringDriveCaller: \"" << s << "\" => \"" << out << "\"" << std::endl);
2481 	}
2482 
2483 	/* allocazione e creazione */
2484 	SAFENEWWITHCONSTRUCTOR(pDC,
2485 		StringDriveCaller,
2486 		StringDriveCaller(pDrvHdl, s, expr));
2487 
2488 #else // ! USE_EE
2489 
2490 // #define TRIM_ALL_SPACES
2491 #define TRIM_ALL_SPACES_BUT_ONE
2492 
2493 #if defined(TRIM_ALL_SPACES)
2494 	for (std::string::iterator i = s.begin(); i != s.end();) {
2495 		if (isspace(*i)) {
2496 			i = s.erase(i);
2497 
2498 		} else {
2499 			++i;
2500 		}
2501 	}
2502 #elif defined(TRIM_ALL_SPACES_BUT_ONE)
2503 	bool bString(false);
2504 	for (std::string::iterator i = s.begin(); i != s.end();) {
2505 		if (isspace(*i)) {
2506 			if (!bString) {
2507 				bString = true;
2508 				++i;
2509 
2510 			} else {
2511 				i = s.erase(i);
2512 			}
2513 
2514 		} else {
2515 			if (bString) {
2516 				bString = false;
2517 			}
2518 			++i;
2519 		}
2520 	}
2521 #endif // TRIM_ALL_SPACES_BUT_ONE
2522 
2523 	DEBUGCOUT("String to evaluate: \"" << s << '\"' << std::endl);
2524 
2525 	/* allocazione e creazione */
2526 	SAFENEWWITHCONSTRUCTOR(pDC,
2527 		StringDriveCaller,
2528 		StringDriveCaller(pDrvHdl, s));
2529 
2530 #endif // ! USE_EE
2531 
2532 	return pDC;
2533 }
2534 
2535 struct DofDCR : public DriveCallerRead {
2536 	DriveCaller *
2537 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2538 };
2539 
2540 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2541 DofDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2542 {
2543 	NeedDM(pDM, HP, bDeferred, "dof");
2544 
2545 	const DriveHandler* pDrvHdl = 0;
2546 	if (pDM != 0) {
2547 		pDrvHdl = pDM->pGetDrvHdl();
2548 	}
2549 
2550 	DriveCaller *pDC = 0;
2551 
2552 	/* driver legato ad un grado di liberta' nodale */
2553 	if (pDM == 0) {
2554 		silent_cerr("sorry, since the driver is not owned by a DataManager" << std::endl
2555 			<< "no DOF dependent drivers are allowed;" << std::endl
2556 			<< "aborting..." << std::endl);
2557 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2558 	}
2559 
2560 	ScalarDof SD = ReadScalarDof(pDM, HP, true, true);
2561 
2562 #ifdef USE_MPI
2563 	if (MPI::Is_initialized() && MBDynComm.Get_size() > 1) {
2564 		silent_cerr("warning: add explicit connection entry for "
2565 			<< psNodeNames[SD.pNode->GetNodeType()]
2566 			<< "(" << SD.pNode->GetLabel() << ") dof drive"
2567 			" at line " << HP.GetLineData() << std::endl);
2568 	}
2569 #endif /* USE_MPI */
2570 
2571 	/* Chiamata ricorsiva a leggere il drive supplementare */
2572 	DriveCaller* pTmp = 0;
2573 	pTmp = HP.GetDriveCaller();
2574 
2575 	/* allocazione e creazione */
2576 	SAFENEWWITHCONSTRUCTOR(pDC,
2577 		DofDriveCaller,
2578 		DofDriveCaller(pDrvHdl, pTmp, SD));
2579 
2580 	return pDC;
2581 }
2582 
2583 /*
2584  * shared by "node" and "element" private data drives
2585  */
2586 struct SimulationEntityDCR : public DriveCallerRead {
2587 protected:
2588 	DriveCaller *
2589 	Read(const DataManager* pDM, MBDynParser& HP,
2590 		const SimulationEntity *pSE, const std::string& msg);
2591 };
2592 
2593 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,const SimulationEntity * pSE,const std::string & msg)2594 SimulationEntityDCR::Read(const DataManager* pDM,
2595 	MBDynParser& HP, const SimulationEntity *pSE, const std::string& msg)
2596 {
2597 	const DriveHandler* pDrvHdl = pDM->pGetDrvHdl();
2598 	DriveCaller *pDC = 0;
2599 
2600 	unsigned int iIndex = 0;
2601 	std::string sIndexName;
2602 	if (HP.IsKeyWord("string")) {
2603 		sIndexName = HP.GetStringWithDelims();
2604 		if (sIndexName.empty()) {
2605 			silent_cerr("empty string for " << msg
2606 				<< " at line " << HP.GetLineData()
2607 				<< std::endl);
2608 			throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2609 		}
2610 		iIndex = pSE->iGetPrivDataIdx(sIndexName.c_str());
2611 		if (iIndex == 0) {
2612 			silent_cerr("illegal string \"" << sIndexName << "\""
2613 				" for " << msg
2614 				<< " at line " << HP.GetLineData()
2615 				<< std::endl);
2616 			throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2617 		}
2618 
2619 	} else if (HP.IsKeyWord("index")) {
2620 		silent_cout("\"index\" deprecated for " << msg
2621 			<< "; use \"string\" instead at line " << HP.GetLineData() << std::endl);
2622 
2623 		iIndex = HP.GetInt();
2624 
2625 	} else if (pSE->iGetNumPrivData() == 1) {
2626 		iIndex = 1;
2627 
2628 	} else {
2629 		silent_cerr("need a private data index for " << msg
2630 			<< " at line " << HP.GetLineData() << std::endl);
2631 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2632 	}
2633 
2634 	if (iIndex < 1 || iIndex > pSE->iGetNumPrivData()) {
2635 		silent_cerr("illegal index " << iIndex << " for " << msg
2636 			<< " at line " << HP.GetLineData() << std::endl);
2637 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2638 	}
2639 
2640 #ifdef USE_MPI
2641 	/* FIXME: todo ... */
2642 	if (MPI::Is_initialized() && MBDynComm.Get_size() > 1) {
2643 		silent_cerr("warning: add explicit connection entry for " << msg
2644 			<< " at line " << HP.GetLineData() << std::endl);
2645 	}
2646 #endif /* USE_MPI */
2647 
2648 	/* Chiamata ricorsiva a leggere il drive supplementare */
2649 	DriveCaller* pTmp = 0;
2650 	pTmp = HP.GetDriveCaller();
2651 
2652 	/* allocazione e creazione */
2653 	SAFENEWWITHCONSTRUCTOR(pDC,
2654 		PrivDriveCaller,
2655 		PrivDriveCaller(pDrvHdl, pTmp, pSE, iIndex, sIndexName.c_str()));
2656 
2657 	return pDC;
2658 }
2659 
2660 struct ElementDCR : public SimulationEntityDCR {
2661 	DriveCaller *
2662 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2663 };
2664 
2665 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2666 ElementDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2667 {
2668 	NeedDM(pDM, HP, bDeferred, "element");
2669 
2670 	/* driver legato ai dati privati di un elemento */
2671 	if (pDM == 0) {
2672 		silent_cerr("since the driver is not owned by a DataManager" << std::endl
2673 			<< "no element dependent drivers are allowed;" << std::endl
2674 			<< "aborting..." << std::endl);
2675 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2676 	}
2677 
2678 	unsigned uLabel = HP.GetInt();
2679 	KeyTable Kel(HP, psReadElemsElems);
2680 	int k = HP.IsKeyWord();
2681 	if (k == -1) {
2682 		const char *s = HP.GetString();
2683 		silent_cerr("unknown element type \"" << s
2684 			<< "\" at line " << HP.GetLineData()
2685 			<< std::endl);
2686 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2687 	}
2688 
2689 	/* Type(Label) */
2690 	std::ostringstream os;
2691 	os << psElemNames[Elem::Type(k)] << "(" << uLabel << ")";
2692 
2693 	const Elem *pElem = pDM->pFindElem(Elem::Type(k), uLabel);
2694 	if (pElem == 0) {
2695 		silent_cerr("unable to find " << os.str() << " at line "
2696 			<< HP.GetLineData() << std::endl);
2697 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2698 	}
2699 
2700 	return SimulationEntityDCR::Read(pDM, HP, pElem, os.str());
2701 }
2702 
2703 struct NodeDCR : public SimulationEntityDCR {
2704 	DriveCaller *
2705 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2706 };
2707 
2708 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2709 NodeDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2710 {
2711 	NeedDM(pDM, HP, bDeferred, "node");
2712 
2713 	/* driver legato ai dati privati di un nodo */
2714 	if (pDM == 0) {
2715 		silent_cerr("since the driver is not owned by a DataManager" << std::endl
2716 			<< "no node dependent drivers are allowed;" << std::endl
2717 			<< "aborting..." << std::endl);
2718 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2719 	}
2720 
2721 	unsigned uLabel = HP.GetInt();
2722 	KeyTable Kel(HP, psReadNodesNodes);
2723 	int k = HP.IsKeyWord();
2724 	if (k == -1) {
2725 		const char *s = HP.GetString();
2726 		silent_cerr("unknown node type \"" << s
2727 			<< "\" at line " << HP.GetLineData()
2728 			<< std::endl);
2729 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2730 	}
2731 
2732 	/* Type(Label) */
2733 	std::ostringstream os;
2734 	os << psNodeNames[Elem::Type(k)] << "(" << uLabel << ")";
2735 
2736 	const Node *pNode = pDM->pFindNode(Node::Type(k), uLabel);
2737 	if (pNode == 0) {
2738 		silent_cerr("unable to find " << os.str() << " at line "
2739 			<< HP.GetLineData() << std::endl);
2740 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2741 	}
2742 
2743 	return SimulationEntityDCR::Read(pDM, HP, pNode, os.str());
2744 }
2745 
2746 struct DriveDCR : public DriveCallerRead {
2747 	DriveCaller *
2748 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2749 };
2750 
2751 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2752 DriveDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2753 {
2754 	const DriveHandler* pDrvHdl = 0;
2755 	if (pDM != 0) {
2756 		pDrvHdl = pDM->pGetDrvHdl();
2757 	}
2758 
2759 	DriveCaller *pDC = 0;
2760 
2761 	DriveCaller *pD1 = HP.GetDriveCaller(bDeferred);
2762 	DriveCaller *pD2 = HP.GetDriveCaller(bDeferred);
2763 
2764 	SAFENEWWITHCONSTRUCTOR(pDC,
2765 		DriveDriveCaller,
2766 		DriveDriveCaller(pDrvHdl, pD1, pD2));
2767 
2768 	return pDC;
2769 }
2770 
2771 struct SHDCR : public DriveCallerRead {
2772 	DriveCaller *
2773 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2774 };
2775 
2776 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2777 SHDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2778 {
2779 	const DriveHandler* pDrvHdl = 0;
2780 	if (pDM != 0) {
2781 		pDrvHdl = pDM->pGetDrvHdl();
2782 	}
2783 
2784 	DriveCaller *pDC = 0;
2785 
2786 	DriveCaller *pFunc = HP.GetDriveCaller(bDeferred);
2787 	DriveCaller *pTrigger = HP.GetDriveCaller(bDeferred);
2788 
2789 	doublereal dVal0 = 0.;
2790 	if (HP.IsKeyWord("initial" "value")) {
2791 		dVal0 = HP.GetReal();
2792 	}
2793 
2794 	SAFENEWWITHCONSTRUCTOR(pDC,
2795 		SHDriveCaller,
2796 		SHDriveCaller(pDrvHdl, pFunc, pTrigger, dVal0));
2797 
2798 	return pDC;
2799 }
2800 
2801 struct ArrayDCR : public DriveCallerRead {
2802 	DriveCaller *
2803 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2804 };
2805 
2806 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2807 ArrayDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2808 {
2809 	const DriveHandler* pDrvHdl = 0;
2810 	if (pDM != 0) {
2811 		pDrvHdl = pDM->pGetDrvHdl();
2812 	}
2813 
2814 	DriveCaller *pDC = 0;
2815 
2816 	/* driver legato ad un grado di liberta' nodale */
2817 	unsigned short int iNumDr = (unsigned short int)HP.GetInt();
2818 	if (iNumDr == 0) {
2819 		silent_cerr("Sorry, at least one driver is required" << std::endl);
2820 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2821 
2822 	/* creazione di un driver normale mediante chiamata ricorsiva */
2823 	} else if (iNumDr == 1) {
2824 		pDC = HP.GetDriveCaller();
2825 
2826 	} else {
2827 		DriveArrayCaller::dcv_t DC(iNumDr);
2828 		for (int i = 0; i < iNumDr; i++) {
2829 			DC[i] = HP.GetDriveCaller();
2830 		}
2831 
2832 		/* allocazione e creazione array */
2833 		SAFENEWWITHCONSTRUCTOR(pDC,
2834 			DriveArrayCaller,
2835 			DriveArrayCaller(pDrvHdl, DC));
2836 	}
2837 
2838 	return pDC;
2839 }
2840 
2841 struct FileDCR : public DriveCallerRead {
2842 	DriveCaller *
2843 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2844 };
2845 
2846 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2847 FileDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2848 {
2849 	NeedDM(pDM, HP, bDeferred, "file");
2850 
2851 	/* driver legato ai driver */
2852 	if (pDM == 0) {
2853 		silent_cerr("sorry, since the driver is not owned by a DataManager" << std::endl
2854 			<< "no driver dependent drivers are allowed;" << std::endl
2855 			<< "aborting..." << std::endl);
2856 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2857 	}
2858 
2859 	const DriveHandler* pDrvHdl = pDM->pGetDrvHdl();
2860 	DriveCaller *pDC = 0;
2861 
2862 	/* drive file */
2863 	/* lettura dei dati specifici */
2864 	unsigned int uL = HP.GetInt();
2865 	FileDrive* pDrv = dynamic_cast<FileDrive*>(pDM->pFindDrive(Drive::FILEDRIVE, uL));
2866 	if (pDrv == 0) {
2867 		silent_cerr("line " << HP.GetLineData()
2868 			<< ": can't find FileDrive(" << uL << ")" << std::endl);
2869 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2870 	}
2871 
2872 	integer id = 1;
2873 
2874 	const char *s = HP.IsWord(fileDriveCallerTypeWordSet);
2875 	if (s != NULL) {
2876 		FileDriveCallerTypeMap::iterator it = fileDriveCallerTypeMap.find(std::string(s));
2877 		id = it->second->Read(pDM, HP, pDrv);
2878 	} else {
2879 		if (HP.IsArg()) {
2880 			id = HP.GetInt(id);
2881 			if (id < 1 || id > pDrv->iGetNumDrives()) {
2882 				silent_cerr("line " << HP.GetLineData()
2883 					<< ": invalid column number " << id
2884 					<< " (must be between 1 and "
2885 					<< pDrv->iGetNumDrives() << ")" << std::endl);
2886 				throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2887 			}
2888 		}
2889 	}
2890 
2891 	doublereal da = 1.;
2892 	if (HP.IsKeyWord("amplitude")) {
2893 		da = HP.GetReal();
2894 	}
2895 
2896 	/* allocazione e creazione */
2897 	SAFENEWWITHCONSTRUCTOR(pDC,
2898 		FileDriveCaller,
2899 		FileDriveCaller(pDrvHdl, pDrv, id, da));
2900 
2901 	return pDC;
2902 }
2903 
2904 /*----------------------------------------------------------------------------
2905 management of FileDriveCaller type
2906 ------------------------------------------------------------------------------
2907 
2908 Coded by Luca Conti (May 2017)
2909 */
2910 
2911 FileDriveCallerTypeMap fileDriveCallerTypeMap;
2912 FileDriveCallerTypeWordSet fileDriveCallerTypeWordSet;
2913 
2914 /* FileDriveCaller type parsing checker: allows the parser
2915 to understand if the next keyword is a FileDriveCaller type */
IsWord(const std::string & s) const2916 bool FileDriveCallerTypeWordSet::IsWord(const std::string& s) const {
2917 		return fileDriveCallerTypeMap.find(std::string(s)) != fileDriveCallerTypeMap.end();
2918 	};
2919 
setFileDriveCallerType(const char * name,FileDriveCallerTypeReader * rf)2920 bool setFileDriveCallerType(const char *name, FileDriveCallerTypeReader *rf){
2921 	pedantic_cout("registering FileDriveCaller type \"" << name << "\""
2922 		<< std::endl );
2923 	return fileDriveCallerTypeMap.insert(FileDriveCallerTypeMap::value_type(name, rf)).second;
2924 }
2925 
DestroyFileDriveCallerTypes(void)2926 void DestroyFileDriveCallerTypes(void){
2927 	for (FileDriveCallerTypeMap::iterator i = fileDriveCallerTypeMap.begin(); i != fileDriveCallerTypeMap.end(); ++i) {
2928 		delete i->second;
2929 	}
2930 	fileDriveCallerTypeMap.clear();
2931 }
2932 
2933 /*---------------------------------------------------------------------------*/
2934 
2935 struct PeriodicDCR : public DriveCallerRead {
2936 	DriveCaller *
2937 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2938 };
2939 
2940 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2941 PeriodicDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2942 {
2943 	NeedDM(pDM, HP, bDeferred, "periodic");
2944 
2945 	/* driver legato ai driver */
2946 	if (pDM == 0) {
2947 		silent_cerr("sorry, since the driver is not owned by a DataManager" << std::endl
2948 			<< "no driver dependent drivers are allowed;" << std::endl
2949 			<< "aborting..." << std::endl);
2950 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2951 	}
2952 
2953 	const DriveHandler* pDrvHdl = pDM->pGetDrvHdl();
2954 	DriveCaller *pDC = 0;
2955 
2956 	doublereal dT0 = HP.GetReal();
2957 	doublereal dPeriod = HP.GetReal();
2958 	if (dPeriod <= 0.) {
2959 		silent_cerr("PeriodicDriveCaller: invalid negative or null period at line " << HP.GetLineData() << std::endl);
2960 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2961 	}
2962 
2963 	const DriveCaller *pDC1 = HP.GetDriveCaller();
2964 
2965 	/* allocazione e creazione */
2966 	SAFENEWWITHCONSTRUCTOR(pDC,
2967 		PeriodicDriveCaller,
2968 		PeriodicDriveCaller(pDrvHdl, pDC1, dT0, dPeriod));
2969 
2970 	return pDC;
2971 }
2972 
2973 
2974 struct PostponedDCR : public DriveCallerRead {
2975 	DriveCaller *
2976 	Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred);
2977 };
2978 
2979 DriveCaller *
Read(const DataManager * pDM,MBDynParser & HP,bool bDeferred)2980 PostponedDCR::Read(const DataManager* pDM, MBDynParser& HP, bool bDeferred)
2981 {
2982 	integer label = HP.GetInt();
2983 	if (label < 0) {
2984 		silent_cerr("PostponedDriveCaller: invalid negative label \"" << label << "\" at line " << HP.GetLineData() << std::endl);
2985 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
2986 	}
2987 
2988 	/* allocazione e creazione */
2989 	DriveCaller *pDC = 0;
2990 	SAFENEWWITHCONSTRUCTOR(pDC,
2991 		PostponedDriveCaller,
2992 		PostponedDriveCaller(HP, unsigned(label)));
2993 
2994 	return pDC;
2995 }
2996 
2997 
2998 
2999 static unsigned d_done;
3000 
3001 void
InitDriveData(void)3002 InitDriveData(void)
3003 {
3004 	if (::d_done++ > 0) {
3005 		return;
3006 	}
3007 
3008 	SetDriveData("fixed" "step", new FixedStepDR);
3009 	SetDriveData("variable" "step", new VariableStepDR);
3010 #ifdef USE_SOCKET
3011 	SetDriveData("socket", new SocketDR);
3012 	SetDriveData("socket" "stream", new StreamDR("socket stream"));
3013 	SetDriveData("rtai" "input", new StreamDR("RTAI input"));
3014 	SetDriveData("stream", new StreamDR);
3015 #endif // USE_SOCKET
3016 	SetDriveData("buffer" "stream", new BufferStreamDR);
3017 
3018 	/* NOTE: add here initialization of new built-in drives;
3019 	 * alternative ways to register new custom drives are:
3020 	 * - call SetDriveData() from anywhere in the code
3021 	 * - write a module that calls SetDriveData() from inside a function
3022 	 *   called module_init(), and run-time load it using "module load"
3023 	 *   in the input file.
3024 	 */
3025 }
3026 
3027 void
DestroyDriveData(void)3028 DestroyDriveData(void)
3029 {
3030 	if (::d_done == 0) {
3031 		silent_cerr("DestroyDriveData() called once too many" << std::endl);
3032 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
3033 	}
3034 
3035 	if (--::d_done > 0) {
3036 		return;
3037 	}
3038 
3039 	/* free stuff */
3040 	for (DriveFuncMapType::iterator i = DriveFuncMap.begin(); i != DriveFuncMap.end(); ++i) {
3041 		delete i->second;
3042 	}
3043 	DriveFuncMap.clear();
3044 }
3045 
3046 
3047 static unsigned dc_done;
3048 
3049 void
InitDriveCallerData(void)3050 InitDriveCallerData(void)
3051 {
3052 	if (::dc_done++ > 0) {
3053 		return;
3054 	}
3055 
3056 	SetDriveCallerData("array", new ArrayDCR);
3057 	SetDriveCallerData("closest" "next", new ClosestNextDCR);
3058 	SetDriveCallerData("const", new ConstDCR);
3059 	SetDriveCallerData("cosine", new CosineDCR);
3060 	SetDriveCallerData("cubic", new CubicDCR);
3061 	SetDriveCallerData("direct", new DirectDCR);
3062 	SetDriveCallerData("dof", new DofDCR);
3063 	SetDriveCallerData("double" "ramp", new DoubleRampDCR);
3064 	SetDriveCallerData("double" "step", new DoubleStepDCR);
3065 	SetDriveCallerData("drive", new DriveDCR);
3066 	SetDriveCallerData("element", new ElementDCR);
3067 	SetDriveCallerData("exponential", new ExponentialDCR);
3068 	SetDriveCallerData("file", new FileDCR);
3069 	SetDriveCallerData("fourier" "series", new FourierSeriesDCR);
3070 	SetDriveCallerData("frequency" "sweep", new FrequencySweepDCR);
3071 	SetDriveCallerData("function", new FunctionDCR);
3072 #ifdef USE_GINAC
3073 	SetDriveCallerData("ginac", new GiNaCDCR);
3074 #endif // USE_GINAC
3075 	SetDriveCallerData("linear", new LinearDCR);
3076 	SetDriveCallerData("meter", new MeterDCR);
3077 	SetDriveCallerData("mult", new MultDCR);
3078 	SetDriveCallerData("node", new NodeDCR);
3079 	SetDriveCallerData("null", new NullDCR);
3080 	SetDriveCallerData("one", new OneDCR);	/* deprecated */
3081 	SetDriveCallerData("parabolic", new ParabolicDCR);
3082 	SetDriveCallerData("periodic", new PeriodicDCR);
3083 	SetDriveCallerData("piecewise" "linear", new PiecewiseLinearDCR);
3084 	SetDriveCallerData("postponed", new PostponedDCR);
3085 	SetDriveCallerData("ramp", new RampDCR);
3086 	SetDriveCallerData("random", new RandomDCR);
3087 	SetDriveCallerData("sample" "and" "hold", new SHDCR);
3088 	SetDriveCallerData("sine", new SineDCR);
3089 	SetDriveCallerData("step", new StepDCR);
3090 	SetDriveCallerData("string", new StringDCR);
3091 	SetDriveCallerData("tanh", new TanhDCR);
3092 	SetDriveCallerData("time", new TimeDCR);
3093 	SetDriveCallerData("timestep", new TimeStepDCR);
3094 	SetDriveCallerData("unit", new OneDCR);
3095 
3096 	/* NOTE: add here initialization of new built-in drive callers;
3097 	 * alternative ways to register new custom drive callers are:
3098 	 * - call SetDriveCallerData() from anywhere in the code
3099 	 * - write a module that calls SetDriveCallerData() from inside a function
3100 	 *   called module_init(), and run-time load it using "module load"
3101 	 *   in the input file.
3102 	 */
3103 #ifdef STATIC_MODULES
3104 #ifdef USE_OCTAVE
3105 	mbdyn_octave_set();
3106 #endif // USE_OCTAVE
3107 	nodedistdrive_set();
3108 	minmaxdrive_set();
3109 #endif // STATIC_MODULES
3110 }
3111 
3112 void
DestroyDriveCallerData(void)3113 DestroyDriveCallerData(void)
3114 {
3115 	if (::dc_done == 0) {
3116 		silent_cerr("DestroyDriveCallerData() called once too many" << std::endl);
3117 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
3118 	}
3119 
3120 	if (--::dc_done > 0) {
3121 		return;
3122 	}
3123 
3124 	/* free stuff */
3125 	for (DriveCallerFuncMapType::iterator i = DriveCallerFuncMap.begin(); i != DriveCallerFuncMap.end(); ++i) {
3126 		delete i->second;
3127 	}
3128 	DriveCallerFuncMap.clear();
3129 }
3130