1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/tpldrive_impl.cc,v 1.27 2017/01/12 14:46:11 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 "myassert.h"
35 #include "mynewmem.h"
36 
37 #include "dataman.h"
38 #include "tpldrive_impl.h"
39 #include "reffrm.h"
40 
41 /* ZeroTplDriveCaller<T> defined in "tpldrive_impl.h",
42  * which includes "tpldrive.h" */
43 
44 template <class T>
45 class NullTDCR : public TplDriveCallerRead<T> {
46 public:
47 	virtual TplDriveCaller<T> *
Read(const DataManager * pDM,MBDynParser & HP)48 	Read(const DataManager* pDM, MBDynParser& HP) {
49 		TplDriveCaller<T>* pTplDC = 0;
50 
51 		SAFENEW(pTplDC, ZeroTplDriveCaller<T>);
52 
53 		return pTplDC;
54 	};
55 };
56 
57 template <class T>
58 class ZeroTDCR : public NullTDCR<T> {
59 public:
60 	virtual TplDriveCaller<T> *
Read(const DataManager * pDM,MBDynParser & HP)61 	Read(const DataManager* pDM, MBDynParser& HP) {
62 		silent_cerr("\"zero\" template drive caller "
63 			"at line " << HP.GetLineData() << " is deprecated; "
64 			"use \"null\" instead" << std::endl);
65 
66 		return NullTDCR<T>::Read(pDM, HP);
67 	};
68 };
69 
70 /* ZeroTplDriveCaller - end */
71 
72 
73 /* SingleTplDriveCaller - begin */
74 
75 template <class T>
76 class SingleTDCR : public TplDriveCallerRead<T> {
77 public:
78 	virtual TplDriveCaller<T> *
Read(const DataManager * pDM,MBDynParser & HP)79 	Read(const DataManager* pDM, MBDynParser& HP) {
80 		T t(mb_zero<T>());
81 
82 		t = GetT(HP, t);
83 
84 		DriveCaller* pDC = HP.GetDriveCaller();
85 
86 		TplDriveCaller<T>* pTplDC = 0;
87 
88 		SAFENEWWITHCONSTRUCTOR(pTplDC,
89 			SingleTplDriveCaller<T>,
90 			SingleTplDriveCaller<T>(pDC, t));
91 
92 		return pTplDC;
93 	};
94 };
95 
96 /* SingleTplDriveCaller - end */
97 
98 
99 /* CompTplDriveCaller - begin */
100 
101 template <class T>
102 class CompTplDriveCaller : public TplDriveCaller<T>, public DriveOwner {
103 protected:
104 	std::vector<DriveCaller *> m_dc;
105 
106 public:
CompTplDriveCaller(std::vector<DriveCaller * > & dc)107 	CompTplDriveCaller(std::vector<DriveCaller *>& dc)
108 	: m_dc(dc)
109 	{
110 		if (typeid(T) == typeid(Vec3)) {
111 			if (dc.size() != 3) {
112 				throw ErrGeneric(MBDYN_EXCEPT_ARGS);
113 			}
114 
115 		} else if (typeid(T) == typeid(Vec6)) {
116 			if (dc.size() != 6) {
117 				throw ErrGeneric(MBDYN_EXCEPT_ARGS);
118 			}
119 
120 		} else {
121 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
122 		}
123 	};
124 
~CompTplDriveCaller(void)125 	~CompTplDriveCaller(void) {
126 		for (unsigned i = 0; i < m_dc.size(); i++) {
127 			delete m_dc[i];
128 		}
129 	};
130 
131 	/* copia */
pCopy(void) const132 	virtual TplDriveCaller<T>* pCopy(void) const {
133 		typedef CompTplDriveCaller<T> dc;
134 		TplDriveCaller<T>* pDC = 0;
135 
136 		std::vector<DriveCaller *> tmpdc(m_dc.size());
137 
138 		for (unsigned i = 0; i < m_dc.size(); i++) {
139 			tmpdc[i] = m_dc[i]->pCopy();
140 		}
141 
142 		SAFENEWWITHCONSTRUCTOR(pDC, dc, dc(tmpdc));
143 
144 		return pDC;
145 	};
146 
147 	/* Scrive il contributo del DriveCaller al file di restart */
Restart(std::ostream & out) const148 	virtual std::ostream& Restart(std::ostream& out) const {
149 		out << "component";
150 
151 		for (unsigned i = 0; i < m_dc.size(); i++) {
152 			out << ", ", m_dc[i]->Restart(out);
153 		}
154 
155 		return out;
156 	};
157 
Restart_int(std::ostream & out) const158 	virtual std::ostream& Restart_int(std::ostream& out) const {
159 		for (unsigned i = 0; i < m_dc.size(); i++) {
160 			out << ", ", m_dc[i]->Restart(out);
161 		}
162 
163 		return out;
164 	};
165 
Get(const doublereal & dVar) const166 	inline T Get(const doublereal& dVar) const {
167 		T t;
168 
169 		for (unsigned i = 0; i < m_dc.size(); i++) {
170 			t(i + 1) = m_dc[i]->dGet(dVar);
171 		}
172 
173 		return t;
174 	};
175 
Get(void) const176 	inline T Get(void) const {
177 		T t;
178 
179 		for (unsigned i = 0; i < m_dc.size(); i++) {
180 			t(i + 1) = m_dc[i]->dGet();
181 		}
182 
183 		return t;
184 	};
185 
186 	/* this is about drives that are differentiable */
bIsDifferentiable(void) const187 	inline bool bIsDifferentiable(void) const {
188 		for (unsigned i = 0; i < m_dc.size(); i++) {
189 			if (!m_dc[i]->bIsDifferentiable()) {
190 				return false;
191 			}
192 		}
193 
194 		return true;
195 	};
196 
GetP(void) const197 	inline T GetP(void) const {
198 		T t;
199 
200 		for (unsigned i = 0; i < m_dc.size(); i++) {
201 			t(i + 1) = m_dc[i]->dGetP();
202 		}
203 
204 		return t;
205 	};
206 
getNDrives(void) const207 	inline int getNDrives(void) const {
208 		return m_dc.size();
209 	};
210 };
211 
212 template <>
213 class CompTplDriveCaller<Mat3x3> : public TplDriveCaller<Mat3x3>, public DriveOwner {
214 protected:
215 	std::vector<DriveCaller *> m_dc;
216 
217 public:
CompTplDriveCaller(std::vector<DriveCaller * > & dc)218 	CompTplDriveCaller(std::vector<DriveCaller *>& dc)
219 	: m_dc(dc)
220 	{
221 		if (dc.size() != 9) {
222 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
223 		}
224 	};
225 
~CompTplDriveCaller(void)226 	~CompTplDriveCaller(void) {
227 		for (unsigned i = 0; i < m_dc.size(); i++) {
228 			delete m_dc[i];
229 		}
230 	};
231 
232 	/* copia */
pCopy(void) const233 	virtual TplDriveCaller<Mat3x3>* pCopy(void) const {
234 		typedef CompTplDriveCaller<Mat3x3> dc;
235 		TplDriveCaller<Mat3x3>* pDC = 0;
236 
237 		std::vector<DriveCaller *> tmpdc(m_dc.size());
238 
239 		for (unsigned i = 0; i < m_dc.size(); i++) {
240 			tmpdc[i] = m_dc[i]->pCopy();
241 		}
242 
243 		SAFENEWWITHCONSTRUCTOR(pDC, dc, dc(tmpdc));
244 
245 		return pDC;
246 	};
247 
248 	/* Scrive il contributo del DriveCaller al file di restart */
Restart(std::ostream & out) const249 	virtual std::ostream& Restart(std::ostream& out) const {
250 		out << "component";
251 
252 		for (unsigned i = 0; i < m_dc.size(); i++) {
253 			out << ", ", m_dc[i]->Restart(out);
254 		}
255 
256 		return out;
257 	};
258 
Restart_int(std::ostream & out) const259 	virtual std::ostream& Restart_int(std::ostream& out) const {
260 		for (unsigned i = 0; i < m_dc.size(); i++) {
261 			out << ", ", m_dc[i]->Restart(out);
262 		}
263 
264 		return out;
265 	};
266 
Get(const doublereal & dVar) const267 	inline Mat3x3 Get(const doublereal& dVar) const {
268 		Mat3x3 t;
269 
270 		for (unsigned i = 0; i < m_dc.size(); i++) {
271 			t(i/3 + 1, i%3 + 1) = m_dc[i]->dGet(dVar);
272 		}
273 
274 		return t;
275 	};
276 
Get(void) const277 	inline Mat3x3 Get(void) const {
278 		Mat3x3 t;
279 
280 		for (unsigned i = 0; i < m_dc.size(); i++) {
281 			t(i/3 + 1, i%3 + 1) = m_dc[i]->dGet();
282 		}
283 
284 		return t;
285 	};
286 
287 	/* this is about drives that are differentiable */
bIsDifferentiable(void) const288 	inline bool bIsDifferentiable(void) const {
289 		for (unsigned i = 0; i < m_dc.size(); i++) {
290 			if (!m_dc[i]->bIsDifferentiable()) {
291 				return false;
292 			}
293 		}
294 
295 		return true;
296 	};
297 
GetP(void) const298 	inline Mat3x3 GetP(void) const {
299 		Mat3x3 t;
300 
301 		for (unsigned i = 0; i < m_dc.size(); i++) {
302 			t(i/3 + 1, i%3 + 1) = m_dc[i]->dGetP();
303 		}
304 
305 		return t;
306 	};
307 
getNDrives(void) const308 	inline int getNDrives(void) const {
309 		return m_dc.size();
310 	};
311 };
312 
313 template <>
314 class CompTplDriveCaller<Mat6x6> : public TplDriveCaller<Mat6x6>, public DriveOwner {
315 protected:
316 	std::vector<DriveCaller *> m_dc;
317 
318 public:
CompTplDriveCaller(std::vector<DriveCaller * > & dc)319 	CompTplDriveCaller(std::vector<DriveCaller *>& dc)
320 	: m_dc(dc)
321 	{
322 		if (dc.size() != 36) {
323 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
324 		}
325 	};
326 
~CompTplDriveCaller(void)327 	~CompTplDriveCaller(void) {
328 		for (unsigned i = 0; i < m_dc.size(); i++) {
329 			delete m_dc[i];
330 		}
331 	};
332 
333 	/* copia */
pCopy(void) const334 	virtual TplDriveCaller<Mat6x6>* pCopy(void) const {
335 		typedef CompTplDriveCaller<Mat6x6> dc;
336 		TplDriveCaller<Mat6x6>* pDC = 0;
337 
338 		std::vector<DriveCaller *> tmpdc(m_dc.size());
339 
340 		for (unsigned i = 0; i < m_dc.size(); i++) {
341 			tmpdc[i] = m_dc[i]->pCopy();
342 		}
343 
344 		SAFENEWWITHCONSTRUCTOR(pDC, dc, dc(tmpdc));
345 
346 		return pDC;
347 	};
348 
349 	/* Scrive il contributo del DriveCaller al file di restart */
Restart(std::ostream & out) const350 	virtual std::ostream& Restart(std::ostream& out) const {
351 		out << "component";
352 
353 		for (unsigned i = 0; i < m_dc.size(); i++) {
354 			out << ", ", m_dc[i]->Restart(out);
355 		}
356 
357 		return out;
358 	};
359 
Restart_int(std::ostream & out) const360 	virtual std::ostream& Restart_int(std::ostream& out) const {
361 		for (unsigned i = 0; i < m_dc.size(); i++) {
362 			out << ", ", m_dc[i]->Restart(out);
363 		}
364 
365 		return out;
366 	};
367 
Get(const doublereal & dVar) const368 	inline Mat6x6 Get(const doublereal& dVar) const {
369 		Mat6x6 t;
370 
371 		for (unsigned i = 0; i < m_dc.size(); i++) {
372 			t(i/6 + 1, i%6 + 1) = m_dc[i]->dGet(dVar);
373 		}
374 
375 		return t;
376 	};
377 
Get(void) const378 	inline Mat6x6 Get(void) const {
379 		Mat6x6 t;
380 
381 		for (unsigned i = 0; i < m_dc.size(); i++) {
382 			t(i/6 + 1, i%6 + 1) = m_dc[i]->dGet();
383 		}
384 
385 		return t;
386 	};
387 
388 	/* this is about drives that are differentiable */
bIsDifferentiable(void) const389 	inline bool bIsDifferentiable(void) const {
390 		for (unsigned i = 0; i < m_dc.size(); i++) {
391 			if (!m_dc[i]->bIsDifferentiable()) {
392 				return false;
393 			}
394 		}
395 
396 		return true;
397 	};
398 
GetP(void) const399 	inline Mat6x6 GetP(void) const {
400 		Mat6x6 t;
401 
402 		for (unsigned i = 0; i < m_dc.size(); i++) {
403 			t(i/6 + 1, i%6 + 1) = m_dc[i]->dGetP();
404 		}
405 
406 		return t;
407 	};
408 
getNDrives(void) const409 	inline int getNDrives(void) const {
410 		return m_dc.size();
411 	};
412 };
413 
414 template <class T>
415 class CompTDCR : public TplDriveCallerRead<T> {
416 public:
417 	virtual TplDriveCaller<T> *
Read(const DataManager * pDM,MBDynParser & HP)418 	Read(const DataManager* pDM, MBDynParser& HP) {
419 		std::vector<DriveCaller *> dc;
420 		unsigned nr = 0, nc = 1;
421 		if (typeid(T) == typeid(Vec3)) {
422 			nr = 3;
423 
424 		} else if (typeid(T) == typeid(Vec6)) {
425 			nr = 6;
426 
427 		} else if (typeid(T) == typeid(Mat3x3)) {
428 			nr = 3;
429 			nc = 3;
430 
431 		} else if (typeid(T) == typeid(Mat6x6)) {
432 			nr = 6;
433 			nc = 6;
434 
435 		} else {
436 			silent_cerr("component template drive used with unknown type" << std::endl);
437 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
438 		}
439 
440 		dc.resize(nr*nc);
441 
442 		if (nc > 1 && HP.IsKeyWord("sym")) {
443 			for (unsigned ir = 0; ir < nr; ir++) {
444 				for (unsigned ic = ir; ic < nc; ic++) {
445 					if (HP.IsKeyWord("inactive")) {
446 						dc[nc*ir + ic] = 0;
447 						SAFENEW(dc[nc*ir + ic], NullDriveCaller);
448 
449 					} else {
450 						dc[nc*ir + ic] = HP.GetDriveCaller();
451 					}
452 
453 					if (ic > ir) {
454 						dc[nc*ic + ir] = dc[nc*ir + ic]->pCopy();
455 					}
456 				}
457 			}
458 
459 		} else if (nc > 1 && HP.IsKeyWord("diag")) {
460 			for (unsigned ir = 0; ir < nr; ir++) {
461 				if (HP.IsKeyWord("inactive")) {
462 					dc[nc*ir + ir] = 0;
463 					SAFENEW(dc[nc*ir + ir], NullDriveCaller);
464 
465 				} else {
466 					dc[nc*ir + ir] = HP.GetDriveCaller();
467 				}
468 
469 				for (unsigned ic = ir + 1; ic < nc; ic++) {
470 					dc[nc*ir + ic] = 0;
471 					SAFENEW(dc[nc*ir + ic], NullDriveCaller);
472 					dc[nc*ic + ir] = dc[nc*ir + ic]->pCopy();
473 				}
474 			}
475 
476 		} else {
477 			for (unsigned i = 0; i < dc.size(); i++) {
478 				if (HP.IsKeyWord("inactive")) {
479 					dc[i] = 0;
480 					SAFENEW(dc[i], NullDriveCaller);
481 
482 				} else {
483 					dc[i] = HP.GetDriveCaller();
484 				}
485 			}
486 		}
487 
488 		TplDriveCaller<T>* pTplDC = 0;
489 
490 		SAFENEWWITHCONSTRUCTOR(pTplDC,
491 			CompTplDriveCaller<T>,
492 			CompTplDriveCaller<T>(dc));
493 
494 		return pTplDC;
495 	};
496 };
497 
498 /* CompTplDriveCaller - end */
499 
500 /* ArrayTplDriveCaller - begin */
501 
502 template <class T>
503 struct DrivesArray {
504 	DriveCaller* pDriveCaller;
505 	T t;
DrivesArrayDrivesArray506 	DrivesArray(void) : pDriveCaller(0), t() {};
507 };
508 
509 template <class T>
510 class ArrayTplDriveCaller : public TplDriveCaller<T> {
511 protected:
512 	std::vector<DrivesArray<T> > m_dc;
513 
514 public:
ArrayTplDriveCaller(std::vector<DrivesArray<T>> & dc)515 	ArrayTplDriveCaller(std::vector<DrivesArray<T> >& dc)
516 	: m_dc(dc) {
517 		ASSERT(!dc.empty());
518 	};
519 
~ArrayTplDriveCaller(void)520 	~ArrayTplDriveCaller(void) {
521 		for (unsigned i = 0; i < m_dc.size(); i++) {
522 			SAFEDELETE(m_dc[i].pDriveCaller);
523 		}
524 	};
525 
526 	/* copia */
pCopy(void) const527 	virtual TplDriveCaller<T>* pCopy(void) const {
528 		std::vector<DrivesArray<T> > dc(m_dc.size());
529 		for (unsigned i = 0; i < m_dc.size(); i++) {
530 			dc[i].pDriveCaller = m_dc[i].pDriveCaller->pCopy();
531 			dc[i].t = m_dc[i].t;
532 		}
533 
534 		typedef ArrayTplDriveCaller<T> dc_t;
535 		TplDriveCaller<T>* pDC = 0;
536 
537 		SAFENEWWITHCONSTRUCTOR(pDC, dc_t, dc_t(dc));
538 
539 		return pDC;
540 	};
541 
542 	/* Scrive il contributo del DriveCaller al file di restart */
Restart(std::ostream & out) const543 	virtual std::ostream& Restart(std::ostream& out) const {
544 		out << "array, " << m_dc.size();
545 		for (unsigned i = 0; i < m_dc.size(); i++) {
546 			out << ", ",
547 				Write(out, m_dc[i].t, ", ") << ", ",
548 				m_dc[i].pDriveCaller->Restart(out);
549 		}
550 		return out;
551 	};
552 
Restart_int(std::ostream & out) const553 	virtual std::ostream& Restart_int(std::ostream& out) const {
554 		for (unsigned i = 0; i < m_dc.size(); i++) {
555 			out << ", ",
556 				Write(out, m_dc[i].t, ", ") << ", ",
557 				m_dc[i].pDriveCaller->Restart(out);
558 		}
559 		return out;
560 	};
561 
Get(const doublereal & dVar) const562 	inline T Get(const doublereal& dVar) const {
563 		T v = mb_zero<T>();
564 		for (unsigned i = 0; i < m_dc.size(); i++) {
565 			v += (m_dc[i].t)*(m_dc[i].pDriveCaller->dGet(dVar));
566 		}
567 		return v;
568 	};
569 
Get(void) const570 	inline T Get(void) const {
571 		T v = mb_zero<T>();
572 		for (unsigned i = 0; i < m_dc.size(); i++) {
573 			v += (m_dc[i].t)*(m_dc[i].pDriveCaller->dGet());
574 		}
575 		return v;
576 	};
577 
bIsDifferentiable(void) const578 	inline bool bIsDifferentiable(void) const {
579 		for (unsigned i = 0; i < m_dc.size(); i++) {
580 			if (!m_dc[i].pDriveCaller->bIsDifferentiable()) {
581 				return false;
582 			}
583 		}
584 		return true;
585 	};
586 
GetP(void) const587 	inline T GetP(void) const {
588 		T v = mb_zero<T>();
589 		for (unsigned i = 0; i < m_dc.size(); i++) {
590 			v += (m_dc[i].t)*(m_dc[i].pDriveCaller->dGetP());
591 		}
592 		return v;
593 	};
594 
getNDrives(void) const595 	inline int getNDrives(void) const {
596 		return m_dc.size();
597 	};
598 };
599 
600 template<>
601 class ArrayTplDriveCaller<doublereal> : public TplDriveCaller<doublereal> {
602 protected:
603 	std::vector<DrivesArray<doublereal> > m_dc;
604 
605 public:
ArrayTplDriveCaller(std::vector<DrivesArray<doublereal>> dc)606 	ArrayTplDriveCaller(std::vector<DrivesArray<doublereal> > dc)
607 	: m_dc(dc) {
608 		ASSERT(!m_dc.empty());
609 	};
610 
~ArrayTplDriveCaller(void)611 	virtual ~ArrayTplDriveCaller(void) {
612 		for (unsigned i = 0; i < m_dc.size(); i++) {
613 			SAFEDELETE(m_dc[i].pDriveCaller);
614 		}
615 	};
616 
617 	/* copia */
pCopy(void) const618 	virtual TplDriveCaller<doublereal>* pCopy(void) const {
619 		std::vector<DrivesArray<doublereal> > dc(m_dc.size());
620 		for (unsigned i = 0; i < m_dc.size(); i++) {
621 			dc[i].pDriveCaller = m_dc[i].pDriveCaller->pCopy();
622 			dc[i].t = m_dc[i].t;
623 		}
624 
625 		typedef ArrayTplDriveCaller<doublereal> dc_t;
626 		TplDriveCaller<doublereal>* pDC = 0;
627 
628 		SAFENEWWITHCONSTRUCTOR(pDC, dc_t, dc_t(dc));
629 
630 		return pDC;
631 	};
632 
633 	/* Scrive il contributo del DriveCaller al file di restart */
Restart(std::ostream & out) const634 	virtual std::ostream& Restart(std::ostream& out) const {
635 		out << "array, " << m_dc.size();
636 		for (unsigned i = 0; i < m_dc.size(); i++) {
637 			out << ", ", m_dc[i].pDriveCaller->Restart(out);
638 		}
639 		return out;
640 	};
641 
Restart_int(std::ostream & out) const642 	virtual std::ostream& Restart_int(std::ostream& out) const {
643 		for (unsigned i = 0; i < m_dc.size(); i++) {
644 			out << ", ", m_dc[i].pDriveCaller->Restart(out);
645 		}
646 		return out;
647 	};
648 
Get(const doublereal & dVar) const649 	inline doublereal Get(const doublereal& dVar) const {
650 		doublereal v = 0.;
651 		for (unsigned i = 0; i < m_dc.size(); i++) {
652 			v += m_dc[i].pDriveCaller->dGet(dVar);
653 		}
654 		return v;
655 	};
656 
Get(void) const657 	inline doublereal Get(void) const {
658 		doublereal v = 0.;
659 		for (unsigned i = 0; i < m_dc.size(); i++) {
660 			v += m_dc[i].pDriveCaller->dGet();
661 		}
662 		return v;
663 	};
664 
getNDrives(void) const665 	inline int getNDrives(void) const {
666 		return m_dc.size();
667 	};
668 };
669 
670 /* Nota: di questa classe non viene scritta esplicitamente la versione
671  *       per reali in quanto il coefficiente moltiplicativo
672  *       puo' essere usato per un'ulteriore pesatura del drive */
673 
674 template <class T>
675 class ArrayTDCR : public SingleTDCR<T> {
676 public:
677 	virtual TplDriveCaller<T> *
Read(const DataManager * pDM,MBDynParser & HP)678 	Read(const DataManager* pDM, MBDynParser& HP) {
679 		unsigned short int iNumDr = HP.GetInt();
680 		if (iNumDr == 0) {
681 			silent_cerr("At least one drive is required "
682 				"in array template drive" << std::endl);
683 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
684 
685 		} else if (iNumDr == 1) {
686 			return SingleTDCR<T>::Read(pDM, HP);
687 		} /* else */
688 
689 		std::vector<DrivesArray<T> > dc(iNumDr);
690 
691 		for (unsigned short int i = 0; i < iNumDr; i++) {
692 			T t(mb_zero<T>());
693 			dc[i].t = GetT(HP, t);
694 			dc[i].pDriveCaller = HP.GetDriveCaller();
695 		}
696 
697 		TplDriveCaller<T>* pTplDC = 0;
698 
699 		SAFENEWWITHCONSTRUCTOR(pTplDC,
700 			ArrayTplDriveCaller<T>,
701 			ArrayTplDriveCaller<T>(dc));
702 
703 		return pTplDC;
704 	};
705 };
706 
707 /* ArrayTplDriveCaller - end */
708 
709 
710 extern doublereal GetT(MBDynParser& HP, const doublereal& t);
711 
GetT(MBDynParser & HP,const T & t)712 template <class T> T GetT(MBDynParser& HP, const T& t)
713 {
714 	return HP.Get(t);
715 }
716 
717 /* template drive caller containers */
718 typedef std::map<std::string, TplDriveCallerRead<doublereal> *, ltstrcase> DC1DFuncMapType;
719 typedef std::map<std::string, TplDriveCallerRead<Vec3> *, ltstrcase> DC3DFuncMapType;
720 typedef std::map<std::string, TplDriveCallerRead<Vec6> *, ltstrcase> DC6DFuncMapType;
721 
722 typedef std::map<std::string, TplDriveCallerRead<Mat3x3> *, ltstrcase> DC3x3DFuncMapType;
723 typedef std::map<std::string, TplDriveCallerRead<Mat6x6> *, ltstrcase> DC6x6DFuncMapType;
724 
725 static DC1DFuncMapType DC1DFuncMap;
726 static DC3DFuncMapType DC3DFuncMap;
727 static DC6DFuncMapType DC6DFuncMap;
728 
729 static DC3x3DFuncMapType DC3x3DFuncMap;
730 static DC6x6DFuncMapType DC6x6DFuncMap;
731 
732 struct DC1DWordSetType : public HighParser::WordSet {
IsWordDC1DWordSetType733 	bool IsWord(const std::string& s) const {
734 		return ::DC1DFuncMap.find(std::string(s)) != ::DC1DFuncMap.end();
735 	};
736 };
737 
738 struct DC3DWordSetType : public HighParser::WordSet {
IsWordDC3DWordSetType739 	bool IsWord(const std::string& s) const {
740 		return ::DC3DFuncMap.find(std::string(s)) != ::DC3DFuncMap.end();
741 	};
742 };
743 
744 struct DC6DWordSetType : public HighParser::WordSet {
IsWordDC6DWordSetType745 	bool IsWord(const std::string& s) const {
746 		return ::DC6DFuncMap.find(std::string(s)) != ::DC6DFuncMap.end();
747 	};
748 };
749 
750 struct DC3x3DWordSetType : public HighParser::WordSet {
IsWordDC3x3DWordSetType751 	bool IsWord(const std::string& s) const {
752 		return ::DC3x3DFuncMap.find(std::string(s)) != ::DC3x3DFuncMap.end();
753 	};
754 };
755 
756 struct DC6x6DWordSetType : public HighParser::WordSet {
IsWordDC6x6DWordSetType757 	bool IsWord(const std::string& s) const {
758 		return ::DC6x6DFuncMap.find(std::string(s)) != ::DC6x6DFuncMap.end();
759 	};
760 };
761 
762 static DC1DWordSetType DC1DWordSet;
763 static DC3DWordSetType DC3DWordSet;
764 static DC6DWordSetType DC6DWordSet;
765 
766 static DC3x3DWordSetType DC3x3DWordSet;
767 static DC6x6DWordSetType DC6x6DWordSet;
768 
769 /* template drive caller registration functions: call to register one */
770 bool
SetDC1D(const char * name,TplDriveCallerRead<doublereal> * rf)771 SetDC1D(const char *name, TplDriveCallerRead<doublereal> *rf)
772 {
773 	pedantic_cout("registering template drive caller 1D \"" << name << "\""
774 		<< std::endl );
775 	return DC1DFuncMap.insert(DC1DFuncMapType::value_type(name, rf)).second;
776 }
777 
778 bool
SetDC3D(const char * name,TplDriveCallerRead<Vec3> * rf)779 SetDC3D(const char *name, TplDriveCallerRead<Vec3> *rf)
780 {
781 	pedantic_cout("registering template drive caller 3D \"" << name << "\""
782 		<< std::endl );
783 	return DC3DFuncMap.insert(DC3DFuncMapType::value_type(name, rf)).second;
784 }
785 
786 bool
SetDC6D(const char * name,TplDriveCallerRead<Vec6> * rf)787 SetDC6D(const char *name, TplDriveCallerRead<Vec6> *rf)
788 {
789 	pedantic_cout("registering template drive caller 6D \"" << name << "\""
790 		<< std::endl );
791 	return DC6DFuncMap.insert(DC6DFuncMapType::value_type(name, rf)).second;
792 }
793 
794 bool
SetDC3x3D(const char * name,TplDriveCallerRead<Mat3x3> * rf)795 SetDC3x3D(const char *name, TplDriveCallerRead<Mat3x3> *rf)
796 {
797 	pedantic_cout("registering template drive caller 3x3D \"" << name << "\""
798 		<< std::endl );
799 	return DC3x3DFuncMap.insert(DC3x3DFuncMapType::value_type(name, rf)).second;
800 }
801 
802 bool
SetDC6x6D(const char * name,TplDriveCallerRead<Mat6x6> * rf)803 SetDC6x6D(const char *name, TplDriveCallerRead<Mat6x6> *rf)
804 {
805 	pedantic_cout("registering template drive caller 6x6D \"" << name << "\""
806 		<< std::endl );
807 	return DC6x6DFuncMap.insert(DC6x6DFuncMapType::value_type(name, rf)).second;
808 }
809 
810 /* functions that read a template drive caller */
811 TplDriveCaller<doublereal> *
ReadDC1D(const DataManager * pDM,MBDynParser & HP)812 ReadDC1D(const DataManager* pDM, MBDynParser& HP)
813 {
814 	const char *s = HP.IsWord(DC1DWordSet);
815 	if (s == 0) {
816 		s = "single";
817 	}
818 
819 	DC1DFuncMapType::iterator func = DC1DFuncMap.find(std::string(s));
820 	if (func == DC1DFuncMap.end()) {
821 		silent_cerr("unknown template drive caller 1D type \"" << s << "\" "
822 			"at line " << HP.GetLineData() << std::endl);
823 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
824 	}
825 
826 	return func->second->Read(pDM, HP);
827 }
828 
829 TplDriveCaller<Vec3> *
ReadDC3D(const DataManager * pDM,MBDynParser & HP)830 ReadDC3D(const DataManager* pDM, MBDynParser& HP)
831 {
832 	const char *s = HP.IsWord(DC3DWordSet);
833 	if (s == 0) {
834 		s = "single";
835 	}
836 
837 	DC3DFuncMapType::iterator func = DC3DFuncMap.find(std::string(s));
838 	if (func == DC3DFuncMap.end()) {
839 		silent_cerr("unknown template drive caller 3D type \"" << s << "\" "
840 			"at line " << HP.GetLineData() << std::endl);
841 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
842 	}
843 
844 	return func->second->Read(pDM, HP);
845 }
846 
847 TplDriveCaller<Vec6> *
ReadDC6D(const DataManager * pDM,MBDynParser & HP)848 ReadDC6D(const DataManager* pDM, MBDynParser& HP)
849 {
850 	const char *s = HP.IsWord(DC6DWordSet);
851 	if (s == 0) {
852 		s = "single";
853 	}
854 
855 	DC6DFuncMapType::iterator func = DC6DFuncMap.find(std::string(s));
856 	if (func == DC6DFuncMap.end()) {
857 		silent_cerr("unknown template drive caller 6D type \"" << s << "\" "
858 			"at line " << HP.GetLineData() << std::endl);
859 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
860 	}
861 
862 	return func->second->Read(pDM, HP);
863 }
864 
865 TplDriveCaller<Mat3x3> *
ReadDC3x3D(const DataManager * pDM,MBDynParser & HP)866 ReadDC3x3D(const DataManager* pDM, MBDynParser& HP)
867 {
868 	const char *s = HP.IsWord(DC3x3DWordSet);
869 	if (s == 0) {
870 		s = "single";
871 	}
872 
873 	DC3x3DFuncMapType::iterator func = DC3x3DFuncMap.find(std::string(s));
874 	if (func == DC3x3DFuncMap.end()) {
875 		silent_cerr("unknown template drive caller 3x3D type \"" << s << "\" "
876 			"at line " << HP.GetLineData() << std::endl);
877 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
878 	}
879 
880 	return func->second->Read(pDM, HP);
881 }
882 
883 TplDriveCaller<Mat6x6> *
ReadDC6x6D(const DataManager * pDM,MBDynParser & HP)884 ReadDC6x6D(const DataManager* pDM, MBDynParser& HP)
885 {
886 	const char *s = HP.IsWord(DC6x6DWordSet);
887 	if (s == 0) {
888 		s = "single";
889 	}
890 
891 	DC6x6DFuncMapType::iterator func = DC6x6DFuncMap.find(std::string(s));
892 	if (func == DC6x6DFuncMap.end()) {
893 		silent_cerr("unknown template drive caller 6x6D type \"" << s << "\" "
894 			"at line " << HP.GetLineData() << std::endl);
895 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
896 	}
897 
898 	return func->second->Read(pDM, HP);
899 }
900 
901 template <class VM>
902 static TplDriveCaller<Vec3> *
ReadDCVec(const DataManager * pDM,MBDynParser & HP,const ReferenceFrame & rf)903 ReadDCVec(const DataManager* pDM, MBDynParser& HP, const ReferenceFrame& rf)
904 {
905 	VM manip(HP, rf);
906 
907 	HP.PushManip(&manip);
908 	TplDriveCaller<Vec3>* pDC = HP.GetTplDriveCaller<Vec3>();
909 	if (HP.GetManip() == &manip) {
910 		HP.PopManip();
911 	}
912 
913 	return pDC;
914 }
915 
916 TplDriveCaller<Vec3> *
ReadDCVecRel(const DataManager * pDM,MBDynParser & HP,const ReferenceFrame & rf)917 ReadDCVecRel(const DataManager* pDM, MBDynParser& HP, const ReferenceFrame& rf)
918 {
919 	return ReadDCVec<MBDynParser::VecRelManip>(pDM, HP, rf);
920 }
921 
922 TplDriveCaller<Vec3> *
ReadDCVecAbs(const DataManager * pDM,MBDynParser & HP,const ReferenceFrame & rf)923 ReadDCVecAbs(const DataManager* pDM, MBDynParser& HP, const ReferenceFrame& rf)
924 {
925 	return ReadDCVec<MBDynParser::VecAbsManip>(pDM, HP, rf);
926 }
927 
928 static unsigned done;
929 
930 void
InitTplDC(void)931 InitTplDC(void)
932 {
933 	if (::done++ > 0) {
934 		return;
935 	}
936 
937 	/* null */
938 	SetDC1D("null", new NullTDCR<doublereal>);
939 	SetDC3D("null", new NullTDCR<Vec3>);
940 	SetDC6D("null", new NullTDCR<Vec6>);
941 
942 	SetDC3x3D("null", new NullTDCR<Mat3x3>);
943 	SetDC6x6D("null", new NullTDCR<Mat6x6>);
944 
945 	/* zero (deprecated) */
946 	SetDC1D("zero", new ZeroTDCR<doublereal>);
947 	SetDC3D("zero", new ZeroTDCR<Vec3>);
948 	SetDC6D("zero", new ZeroTDCR<Vec6>);
949 
950 	SetDC3x3D("zero", new ZeroTDCR<Mat3x3>);
951 	SetDC6x6D("zero", new ZeroTDCR<Mat6x6>);
952 
953 	/* single */
954 	SetDC1D("single", new SingleTDCR<doublereal>);
955 	SetDC3D("single", new SingleTDCR<Vec3>);
956 	SetDC6D("single", new SingleTDCR<Vec6>);
957 
958 	SetDC3x3D("single", new SingleTDCR<Mat3x3>);
959 	SetDC6x6D("single", new SingleTDCR<Mat6x6>);
960 
961 	/* component */
962 	/* in the scalar case, "single" and "component" are identical */
963 	SetDC1D("component", new SingleTDCR<doublereal>);
964 	SetDC3D("component", new CompTDCR<Vec3>);
965 	SetDC6D("component", new CompTDCR<Vec6>);
966 
967 	SetDC3x3D("component", new CompTDCR<Mat3x3>);
968 	SetDC6x6D("component", new CompTDCR<Mat6x6>);
969 
970 	/* array */
971 	SetDC1D("array", new ArrayTDCR<doublereal>);
972 	SetDC3D("array", new ArrayTDCR<Vec3>);
973 	SetDC6D("array", new ArrayTDCR<Vec6>);
974 
975 	SetDC3x3D("array", new ArrayTDCR<Mat3x3>);
976 	SetDC6x6D("array", new ArrayTDCR<Mat6x6>);
977 }
978 
979 void
DestroyTplDC(void)980 DestroyTplDC(void)
981 {
982 	if (::done == 0) {
983 		silent_cerr("DestroyTplDC() called once too many" << std::endl);
984 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
985 	}
986 
987 	if (--::done > 0) {
988 		return;
989 	}
990 
991 	/* free stuff */
992 	for (DC1DFuncMapType::iterator i = DC1DFuncMap.begin(); i != DC1DFuncMap.end(); ++i) {
993 		delete i->second;
994 	}
995 	DC1DFuncMap.clear();
996 
997 	for (DC3DFuncMapType::iterator i = DC3DFuncMap.begin(); i != DC3DFuncMap.end(); ++i) {
998 		delete i->second;
999 	}
1000 	DC3DFuncMap.clear();
1001 
1002 	for (DC6DFuncMapType::iterator i = DC6DFuncMap.begin(); i != DC6DFuncMap.end(); ++i) {
1003 		delete i->second;
1004 	}
1005 	DC6DFuncMap.clear();
1006 
1007 	for (DC3x3DFuncMapType::iterator i = DC3x3DFuncMap.begin(); i != DC3x3DFuncMap.end(); ++i) {
1008 		delete i->second;
1009 	}
1010 	DC3x3DFuncMap.clear();
1011 
1012 	for (DC6x6DFuncMapType::iterator i = DC6x6DFuncMap.begin(); i != DC6x6DFuncMap.end(); ++i) {
1013 		delete i->second;
1014 	}
1015 	DC6x6DFuncMap.clear();
1016 }
1017 
1018