1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/streamoutelem.cc,v 1.26 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 /*
33  * Portions Copyright Michele Attolico <attolico@aero.polimi.it>
34  */
35 
36 #include "mbconfig.h"           /* This goes first in every *.c,*.cc file */
37 
38 #include "dataman.h"
39 #include "streamoutelem.h"
40 #include "geomdata.h"
41 #include "socketstream_out_elem.h"
42 #include "bufferstream_out_elem.h"
43 #include "socketstreammotionelem.h"
44 #include "bufmod.h"
45 
46 /* StreamOutElem - begin */
47 
StreamOutElem(unsigned int uL,const std::string & name,unsigned int oe)48 StreamOutElem::StreamOutElem(unsigned int uL,
49 	const std::string& name,
50 	unsigned int oe)
51 : Elem(uL, flag(0)),
52 name(name),
53 OutputEvery(oe), OutputCounter(0)
54 {
55 	ASSERT(OutputEvery > 0);
56 }
57 
~StreamOutElem(void)58 StreamOutElem::~StreamOutElem(void)
59 {
60 	NO_OP;
61 }
62 
63 Elem::Type
GetElemType(void) const64 StreamOutElem::GetElemType(void) const
65 {
66 	return Elem::SOCKETSTREAM_OUTPUT;
67 }
68 
69 void
WorkSpaceDim(integer * piRows,integer * piCols) const70 StreamOutElem::WorkSpaceDim(integer* piRows, integer* piCols) const
71 {
72 	*piRows = 0;
73 	*piCols = 0;
74 }
75 
76 SubVectorHandler&
AssRes(SubVectorHandler & WorkVec,doublereal dCoef,const VectorHandler & X,const VectorHandler & XP)77 StreamOutElem::AssRes(SubVectorHandler& WorkVec, doublereal dCoef,
78 		const VectorHandler& X, const VectorHandler& XP)
79 {
80 	WorkVec.Resize(0);
81 	return WorkVec;
82 }
83 
84 VariableSubMatrixHandler&
AssJac(VariableSubMatrixHandler & WorkMat,doublereal dCoef,const VectorHandler & X,const VectorHandler & XP)85 StreamOutElem::AssJac(VariableSubMatrixHandler& WorkMat, doublereal dCoef,
86 		const VectorHandler& X, const VectorHandler& XP)
87 {
88 	WorkMat.SetNullMatrix();
89 	return WorkMat;
90 }
91 
92 /* StreamOutElem - end */
93 
94 
95 /* StreamContent - begin */
96 
StreamContent(size_t size,StreamContent::Modifier * pMod)97 StreamContent::StreamContent(size_t size, StreamContent::Modifier *pMod)
98 : buf(size), m_pMod(pMod)
99 {
100 	if (m_pMod == 0) {
101 		m_pMod = new StreamContent::Copy(size, &buf[0]);
102 
103 	} else {
104 		m_pMod->Set(size, &buf[0]);
105 	}
106 }
107 
~StreamContent(void)108 StreamContent::~StreamContent(void)
109 {
110 	if (m_pMod != 0) {
111 		delete m_pMod;
112 		m_pMod = 0;
113 	}
114 }
115 
116 void *
GetBuf(void) const117 StreamContent::GetBuf(void) const
118 {
119 	return (void *)&buf[0];
120 }
121 
122 int
GetSize(void) const123 StreamContent::GetSize(void) const
124 {
125 	return buf.size();
126 }
127 
128 const void *
GetOutBuf(void) const129 StreamContent::GetOutBuf(void) const
130 {
131 	return m_pMod->GetOutBuf();
132 }
133 
134 int
GetOutSize(void) const135 StreamContent::GetOutSize(void) const
136 {
137 	return m_pMod->GetOutSize();
138 }
139 
~Modifier(void)140 StreamContent::Modifier::~Modifier(void)
141 {
142 	NO_OP;
143 }
144 
Copy(size_t size,const char * outbuf)145 StreamContent::Copy::Copy(size_t size, const char *outbuf)
146 : m_size(size), m_outbuf(outbuf)
147 {
148 	NO_OP;
149 }
150 
151 void
Set(size_t size,const char * outbuf)152 StreamContent::Copy::Set(size_t size, const char *outbuf)
153 {
154 	m_size = size;
155 	m_outbuf = outbuf;
156 }
157 
158 void
Modify(void)159 StreamContent::Copy::Modify(void)
160 {
161 	NO_OP;
162 }
163 
164 const void *
GetOutBuf(void) const165 StreamContent::Copy::GetOutBuf(void) const
166 {
167 	return m_outbuf;
168 }
169 
170 int
GetOutSize(void) const171 StreamContent::Copy::GetOutSize(void) const
172 {
173 	return m_size;
174 }
175 
StreamContentCopyCast(size_t size,const char * buf,size_t outsize,const std::vector<BufCast * > & data)176 StreamContentCopyCast::StreamContentCopyCast(size_t size, const char *buf, size_t outsize, const std::vector<BufCast *>& data)
177 : m_size(size), m_buf(buf), m_outbuf(outsize), m_data(data)
178 {
179 #ifdef DEBUG
180 	std::vector<BufCast *>::const_iterator i = data.end();
181 	ASSERT(i > data.begin());
182 	--i;
183 	size_t minsize = (*i)->offset() + (*i)->size();
184 	ASSERT(outsize >= minsize);
185 #endif
186 }
187 
188 void
Set(size_t size,const char * buf)189 StreamContentCopyCast::Set(size_t size, const char *buf)
190 {
191 	m_size = size;
192 	m_buf = buf;
193 
194 	// FIXME: what about outbuf?
195 	// in principle, size is sizeof(doublereal)*nChannels
196 	ASSERT(m_size == sizeof(doublereal)*m_data.size());
197 }
198 
199 void
Modify(void)200 StreamContentCopyCast::Modify(void)
201 {
202 	ASSERT(m_size == m_data.size()*sizeof(doublereal));
203 
204 	doublereal *rbuf = (doublereal *)&m_buf[0];
205 	for (size_t i = 0; i < m_data.size(); i++) {
206 		m_data[i]->uncast(&m_outbuf[0], rbuf[i]);
207 	}
208 }
209 
210 const void *
GetOutBuf(void) const211 StreamContentCopyCast::GetOutBuf(void) const
212 {
213 	return &m_outbuf[0];
214 }
215 
216 int
GetOutSize(void) const217 StreamContentCopyCast::GetOutSize(void) const
218 {
219 	return m_outbuf.size();
220 }
221 
222 /* StreamContent - end */
223 
224 
225 /* StreamContentValue - begin */
226 
StreamContentValue(const std::vector<ScalarValue * > & v,StreamContent::Modifier * pMod)227 StreamContentValue::StreamContentValue(const std::vector<ScalarValue *>& v,
228 	StreamContent::Modifier *pMod)
229 : StreamContent(sizeof(doublereal)*v.size(), pMod), Values(v)
230 {
231 	ASSERT(Values.size() > 0);
232 }
233 
~StreamContentValue(void)234 StreamContentValue::~StreamContentValue(void)
235 {
236 	for (std::vector<ScalarValue *>::iterator i = Values.begin();
237 		i != Values.end(); ++i)
238 	{
239 		delete *i;
240 	}
241 }
242 
243 void
Prepare(void)244 StreamContentValue::Prepare(void)
245 {
246 	char *curbuf = &buf[0];
247 	for (std::vector<ScalarValue *>::iterator i = Values.begin(); i != Values.end(); ++i) {
248 		/* assign value somewhere into mailbox buffer */
249 		doublereal v = (*i)->dGetValue();
250 
251 		doublereal *dbuf = (doublereal *)curbuf;
252 		dbuf[0] = v;
253 
254 		curbuf += sizeof(doublereal);
255 	}
256 
257 	m_pMod->Modify();
258 }
259 
260 unsigned
GetNumChannels(void) const261 StreamContentValue::GetNumChannels(void) const
262 {
263 	return Values.size();
264 }
265 
266 /* StreamContentValue - end */
267 
268 /*
269  * NOTE: the use of type to determine what type of stream contents
270  * to read is only a hack; needs improvements
271  */
272 
273 StreamContent::Modifier *
ReadStreamContentModifier(MBDynParser & HP,integer nCh)274 ReadStreamContentModifier(MBDynParser& HP, integer nCh)
275 {
276 	StreamContent::Modifier *pSCM(0);
277 
278 	if (HP.IsKeyWord("copy" "cast")) {
279 		std::vector<BufCast *> data(nCh);
280 		ReadBufCast(HP, data);
281 		size_t minsize = data[data.size() - 1]->offset() + data[data.size() - 1]->size();
282 		size_t size = minsize;
283 		if (HP.IsKeyWord("size")) {
284 			integer i = HP.GetInt();
285 			if (i <= 0) {
286 				silent_cerr("ReadStreamContentModifier: invalid size " << i
287 					<< " at line " << HP.GetLineData() << std::endl);
288 				throw ErrGeneric(MBDYN_EXCEPT_ARGS);
289 			}
290 
291 			size = size_t(i);
292 			if (size < minsize) {
293 				silent_cerr("ReadStreamContentModifier: size " << size
294 					<< " is less than min size " << minsize
295 					<< " at line " << HP.GetLineData() << std::endl);
296 				throw ErrGeneric(MBDYN_EXCEPT_ARGS);
297 			}
298 		}
299 
300 		pSCM = new StreamContentCopyCast(0, 0, size, data);
301 
302 	} else if (!HP.IsKeyWord("copy")) {
303 		silent_cerr("ReadStreamContentModifier: unknown modifier type at line " << HP.GetLineData() << std::endl);
304 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
305 	}
306 
307 	return pSCM;
308 }
309 
310 #if 0
311 StreamContent *
312 ReadStreamContent(DataManager *pDM, MBDynParser& HP, StreamContent::Type type)
313 {
314 	switch (type) {
315 	case StreamContent::UNKNOWN:
316 		type = StreamContent::VALUES;
317 		// fallthru
318 
319 	case StreamContent::VALUES:
320 		if (HP.IsKeyWord("motion")) {
321 			type = StreamContent::MOTION;
322 
323 		} else if (!HP.IsKeyWord("values")) {
324 			silent_cerr("ReadStreamContent: "
325 				"missing type, assuming \"values\" "
326 				"at line " << HP.GetLineData() << std::endl);
327 		}
328 		break;
329 
330 	default:
331 		break;
332 	}
333 
334 	StreamContent *pSC = 0;
335 	switch (type) {
336 	case StreamContent::VALUES: {
337 		int nch = HP.GetInt();
338 		if (nch <= 0) {
339 			silent_cerr("illegal number of channels for StreamContent "
340 				"at line " << HP.GetLineData() << std::endl);
341 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
342 		}
343 
344 		std::vector<ScalarValue *> Values(nch);
345 		ReadScalarValues(pDM, HP, Values);
346 
347 		StreamContent::Modifier *pMod(0);
348 		if (HP.IsKeyWord("modifier")) {
349 			pMod = ReadStreamContentModifier(HP, nch);
350 		}
351 
352 		SAFENEWWITHCONSTRUCTOR(pSC, StreamContentValue, StreamContentValue(Values, pMod));
353 		} break;
354 
355 	case StreamContent::MOTION: {
356 		unsigned uFlags = GeometryData::X;
357 		if (HP.IsKeyWord("output" "flags")) {
358 			uFlags = 0;
359 			while (true) {
360 				if (HP.IsKeyWord("position")) {
361 					if (uFlags & GeometryData::X) {
362 						silent_cerr("StreamContent: "
363 							"position flag already defined "
364 							"at line " << HP.GetLineData()
365 							<< std::endl);
366 						throw ErrGeneric(MBDYN_EXCEPT_ARGS);
367 					}
368 					uFlags |= GeometryData::X;
369 
370 				} else if (HP.IsKeyWord("orientation" "matrix")) {
371 					if (uFlags & GeometryData::ORIENTATION_MASK) {
372 						silent_cerr("StreamContent: "
373 							"orientation flag already defined "
374 							"at line " << HP.GetLineData()
375 							<< std::endl);
376 						throw ErrGeneric(MBDYN_EXCEPT_ARGS);
377 					}
378 					uFlags |= GeometryData::R;
379 
380 				} else if (HP.IsKeyWord("orientation" "matrix" "transpose")) {
381 					if (uFlags & GeometryData::ORIENTATION_MASK) {
382 						silent_cerr("StreamContent: "
383 							"orientation flag already defined "
384 							"at line " << HP.GetLineData()
385 							<< std::endl);
386 						throw ErrGeneric(MBDYN_EXCEPT_ARGS);
387 					}
388 					uFlags |= GeometryData::RT;
389 
390 				} else if (HP.IsKeyWord("velocity")) {
391 					if (uFlags & GeometryData::V) {
392 						silent_cerr("StreamContent: "
393 							"velocity flag already defined "
394 							"at line " << HP.GetLineData()
395 							<< std::endl);
396 						throw ErrGeneric(MBDYN_EXCEPT_ARGS);
397 					}
398 					uFlags |= GeometryData::V;
399 
400 				} else if (HP.IsKeyWord("angular" "velocity")) {
401 					if (uFlags & GeometryData::W) {
402 						silent_cerr("StreamContent: "
403 							"angular velocity flag already defined "
404 							"at line " << HP.GetLineData()
405 							<< std::endl);
406 						throw ErrGeneric(MBDYN_EXCEPT_ARGS);
407 					}
408 					uFlags |= GeometryData::W;
409 
410 				} else {
411 					break;
412 				}
413 			}
414 		}
415 
416 		std::vector<const StructNode *> nodes;
417 		if (HP.IsKeyWord("all")) {
418 
419 			DataManager::NodeContainerType::const_iterator i = pDM->begin(Node::STRUCTURAL);
420 			DataManager::NodeContainerType::const_iterator e = pDM->end(Node::STRUCTURAL);
421 
422 			if (e == i) {
423 				silent_cerr("ReadStreamContent: no structural nodes " << std::endl);
424 				throw ErrGeneric(MBDYN_EXCEPT_ARGS);
425 			}
426 
427 			for (; i != e; ++i) {
428 				const StructDispNode *pN = dynamic_cast<const StructDispNode *>(i->second);
429 				const StructNode *pSN = dynamic_cast<const StructNode *>(pN);
430 				ASSERT(pN != 0);
431 					if (pSN && pSN->GetStructNodeType() == StructNode::DUMMY) {
432 					continue;
433 					}
434 
435 				nodes.insert(nodes.end(), pSN);
436 			}
437 
438 		} else {
439 			while (HP.IsArg()) {
440 				nodes.insert(nodes.end(), pDM->ReadNode<const StructNode, Node::STRUCTURAL>(HP));
441 			}
442 		}
443 
444 		// FIXME: right now, we don't modify stream motion stuff
445 		StreamContent::Modifier *pMod(0);
446 
447 		SAFENEWWITHCONSTRUCTOR(pSC, StreamContentMotion, StreamContentMotion(uFlags, nodes, pMod));
448 		} break;
449 
450 	default:
451 		silent_cerr("ReadStreamContent: unknown type "
452 			"at line " << HP.GetLineData() << std::endl);
453 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
454 	}
455 
456 	return pSC;
457 }
458 #endif
459 
460 /* StreamOutEcho - begin */
461 
StreamOutEcho(std::string & sOutFileName,int iPrecision,doublereal dShift)462 StreamOutEcho::StreamOutEcho(std::string& sOutFileName, int iPrecision, doublereal dShift)
463 : sOutFileName(sOutFileName),
464 iPrecision(iPrecision),
465 dShift(dShift)
466 {
467 	NO_OP;
468 }
469 
~StreamOutEcho(void)470 StreamOutEcho::~StreamOutEcho(void)
471 {
472 	NO_OP;
473 }
474 
475 bool
Init(const std::string & msg,unsigned uLabel,unsigned nChannels)476 StreamOutEcho::Init(const std::string& msg, unsigned uLabel, unsigned nChannels)
477 {
478 	outFile.open(sOutFileName.c_str());
479 	if (!outFile) {
480 		silent_cerr(msg << "(" << uLabel << "): "
481 			"unable to open echo file \"" << sOutFileName << "\"" << std::endl);
482 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
483 	}
484 
485 	if (iPrecision > 0) {
486 		outFile.precision(iPrecision);
487 	}
488 	outFile.setf(std::ios::scientific);
489 
490 	outFile
491 		<< "# generated by " << msg << "(" << uLabel << ")"
492 		<< std::endl;
493 	if (nChannels == 1) {
494 		outFile
495 			<< "# Channel #1"
496 			<< std::endl;
497 
498 	} else {
499 		outFile
500 			<< "# Channels #1-" << nChannels
501 			<< std::endl;
502 	}
503 
504 	return true;
505 }
506 
507 void
Echo(const doublereal * pbuf,unsigned size)508 StreamOutEcho::Echo(const doublereal *pbuf, unsigned size)
509 {
510 	outFile << pbuf[0];
511 	for (unsigned i = 1; i < size; i++) {
512 		outFile << " " << pbuf[i];
513 	}
514 	outFile << std::endl;
515 }
516 
517 StreamOutEcho *
ReadStreamOutEcho(MBDynParser & HP)518 ReadStreamOutEcho(MBDynParser& HP)
519 {
520 	StreamOutEcho *pSOE(0);
521 
522 	std::string sOutFileName;
523 	int iPrecision = -1;
524 	doublereal dShift = 0.;
525 
526 	if (HP.IsKeyWord("echo")) {
527 		const char *s = HP.GetFileName();
528 		if (s == NULL) {
529 			silent_cerr("ReadStreamOutEcho: "
530 				"unable to parse echo file name "
531 				"at line " << HP.GetLineData()
532 				<< std::endl);
533 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
534 		}
535 
536 		sOutFileName = s;
537 
538 		if (HP.IsKeyWord("precision")) {
539 			iPrecision = HP.GetInt();
540 			if (iPrecision <= 0) {
541 				silent_cerr("ReadStreamOutEcho: "
542 					"invalid echo precision " << iPrecision
543 					<< " at line " << HP.GetLineData()
544 					<< std::endl);
545 				throw ErrGeneric(MBDYN_EXCEPT_ARGS);
546 			}
547 		}
548 
549 		if (HP.IsKeyWord("shift")) {
550 			dShift = HP.GetReal();
551 		}
552 
553 		pSOE = new StreamOutEcho(sOutFileName, iPrecision, dShift);
554 	}
555 
556 	return pSOE;
557 }
558 
559 /* StreamOutEcho - end */
560 
561 Elem *
ReadOutputElem(DataManager * pDM,MBDynParser & HP,unsigned int uLabel,StreamOutElem::Type eType,StreamContent::Type sType)562 ReadOutputElem(DataManager *pDM, MBDynParser& HP, unsigned int uLabel, StreamOutElem::Type eType, StreamContent::Type sType)
563 {
564 	Elem *pE(0);
565 
566 	if (eType == StreamOutElem::UNDEFINED) {
567 		sType = StreamContent::UNKNOWN;
568 
569 		if (HP.IsKeyWord("socket" "stream")) {
570 			eType = StreamOutElem::SOCKETSTREAM;
571 
572 		} else if (HP.IsKeyWord("buffer" "stream")) {
573 			eType = StreamOutElem::BUFFERSTREAM;
574 
575 		} else {
576 			silent_cerr("ReadOutputElem(" << uLabel << "): "
577 				"unknown \"type\" at line " << HP.GetLineData() << std::endl);
578 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
579 		}
580 	}
581 
582 	switch (eType) {
583 	case StreamOutElem::SOCKETSTREAM:
584 		pE = ReadSocketStreamElem(pDM, HP, uLabel, sType);
585 		break;
586 
587 	case StreamOutElem::BUFFERSTREAM:
588 		pE = ReadBufferStreamElem(pDM, HP, uLabel, sType);
589 		break;
590 
591 	default:
592 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
593 	}
594 
595 	return pE;
596 }
597 
598 /*----------------------------------------------------------------------------
599 management of 'content type' for stream output element ('values','motion', etc)
600 ------------------------------------------------------------------------------
601 
602 Rearranged by Luca Conti (May 2017) on the basis of previous existing code
603 (fully working, just rearranged).
604 
605 Edited in order to apply the same mechanism with 'readers' and 'maps' (std::map)
606   already in use for constitutive laws and drives
607 */
608 
609 StreamOutputContentTypeMap streamOutputContentTypeMap;
610 StreamOutputContentTypeWordSetType streamOutputContentTypeWordSet;
611 unsigned streamOutputInitFunctionCalls = 0;
612 
613 /* content type search inside of the content-type bag: execution of its Read method */
ReadStreamContent(DataManager * pDM,MBDynParser & HP,StreamContent::Type type)614 StreamContent* ReadStreamContent(DataManager *pDM, MBDynParser& HP, StreamContent::Type type) {
615 	//searches in the bag the content type found in MBDyn input file
616 	const char *s = HP.IsWord(streamOutputContentTypeWordSet);
617 
618 	StreamOutputContentTypeMap::iterator it = streamOutputContentTypeMap.find(std::string(s));
619 	if (it == streamOutputContentTypeMap.end()) {
620 		silent_cerr("[streamoutelem.cc] ReadStreamContent:unknown stream output content type "
621 			"\"" << s << "\" "
622 			"at line " << HP.GetLineData() << std::endl);
623 		throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
624 	}
625 	return it->second->Read(pDM, HP);
626 }
627 
628 /* default content type options: reader for 'motion' */
Read(DataManager * pDM,MBDynParser & HP)629 StreamContent* MotionContentTypeReader::Read(DataManager* pDM, MBDynParser& HP) {
630 		// instructions executed for 'motion' case content type
631 
632 			StreamContent* pSC;
633 
634 			unsigned uFlags = GeometryData::X;
635 			if (HP.IsKeyWord("output" "flags")) {
636 				uFlags = 0;
637 				while (true) {
638 					if (HP.IsKeyWord("position")) {
639 						if (uFlags & GeometryData::X) {
640 							silent_cerr("StreamContent: "
641 								"position flag already defined "
642 								"at line " << HP.GetLineData()
643 								<< std::endl);
644 							throw ErrGeneric(MBDYN_EXCEPT_ARGS);
645 						}
646 						uFlags |= GeometryData::X;
647 
648 					} else if (HP.IsKeyWord("orientation" "matrix")) {
649 						if (uFlags & GeometryData::ORIENTATION_MASK) {
650 							silent_cerr("StreamContent: "
651 								"orientation flag already defined "
652 								"at line " << HP.GetLineData()
653 								<< std::endl);
654 							throw ErrGeneric(MBDYN_EXCEPT_ARGS);
655 						}
656 						uFlags |= GeometryData::R;
657 
658 					} else if (HP.IsKeyWord("orientation" "matrix" "transpose")) {
659 						if (uFlags & GeometryData::ORIENTATION_MASK) {
660 							silent_cerr("StreamContent: "
661 								"orientation flag already defined "
662 								"at line " << HP.GetLineData()
663 								<< std::endl);
664 							throw ErrGeneric(MBDYN_EXCEPT_ARGS);
665 						}
666 						uFlags |= GeometryData::RT;
667 
668 					} else if (HP.IsKeyWord("velocity")) {
669 						if (uFlags & GeometryData::V) {
670 							silent_cerr("StreamContent: "
671 								"velocity flag already defined "
672 								"at line " << HP.GetLineData()
673 								<< std::endl);
674 							throw ErrGeneric(MBDYN_EXCEPT_ARGS);
675 						}
676 						uFlags |= GeometryData::V;
677 
678 					} else if (HP.IsKeyWord("angular" "velocity")) {
679 						if (uFlags & GeometryData::W) {
680 							silent_cerr("StreamContent: "
681 								"angular velocity flag already defined "
682 								"at line " << HP.GetLineData()
683 								<< std::endl);
684 							throw ErrGeneric(MBDYN_EXCEPT_ARGS);
685 						}
686 						uFlags |= GeometryData::W;
687 
688 					} else {
689 						break;
690 					}
691 				}
692 			}
693 
694 			std::vector<const StructNode *> nodes;
695 			if (HP.IsKeyWord("all")) {
696 				/* FIXME: todo */
697 
698 			} else {
699 				while (HP.IsArg()) {
700 					nodes.insert(nodes.end(), pDM->ReadNode<const StructNode, Node::STRUCTURAL>(HP));
701 				}
702 			}
703 
704 			// FIXME: right now, we don't modify stream motion stuff
705 			StreamContent::Modifier *pMod(0);
706 
707 			SAFENEWWITHCONSTRUCTOR(pSC, StreamContentMotion, StreamContentMotion(uFlags, nodes, pMod));
708 
709 			return pSC;
710 	}
711 
712 /* default content type options: reader for 'values' */
Read(DataManager * pDM,MBDynParser & HP)713 StreamContent* ValuesContentTypeReader::Read(DataManager* pDM, MBDynParser& HP) {
714 		/* instructions executed for 'values' case content type */
715 
716 			StreamContent* pSC;
717 
718 			int nch = HP.GetInt();
719 			if (nch <= 0) {
720 				silent_cerr("illegal number of channels for StreamContent "
721 					"at line " << HP.GetLineData() << std::endl);
722 				throw ErrGeneric(MBDYN_EXCEPT_ARGS);
723 			}
724 
725 			std::vector<ScalarValue *> Values(nch);
726 			ReadScalarValues(pDM, HP, Values);
727 
728 			StreamContent::Modifier *pMod(0);
729 			if (HP.IsKeyWord("modifier")) {
730 				pMod = ReadStreamContentModifier(HP, nch);
731 			}
732 
733 			SAFENEWWITHCONSTRUCTOR(pSC, StreamContentValue, StreamContentValue(Values, pMod));
734 
735 			return pSC;
736 	}
737 
738 	/* stream output content type parsing checker: allows the parser
739 	to understand if the next keyword is a content type */
IsWord(const std::string & s) const740 	bool StreamOutputContentTypeWordSetType::IsWord(const std::string& s) const {
741 			return streamOutputContentTypeMap.find(std::string(s)) != streamOutputContentTypeMap.end();
742 		};
743 
744 	/*registration function: CALL IT TO REGISTER A NEW CONTENT TYPE -
745 		it is also used by InitStreamOutputContentTypes(void) in order to load default options ('values','motion') */
SetStreamOutputContentType(const char * name,StreamOutputContentTypeReader * rf)746 	bool SetStreamOutputContentType(const char *name, StreamOutputContentTypeReader *rf){
747 		pedantic_cout("registering stream output content type \"" << name << "\""
748 			<< std::endl );
749 		return streamOutputContentTypeMap.insert(StreamOutputContentTypeMap::value_type(name, rf)).second;
750 	}
751 
752 	/* initialization function: called by mbpar.cc in order to load default options ('values','motion')*/
InitStreamOutputContentTypes(void)753 	void InitStreamOutputContentTypes(void){
754 		if (streamOutputInitFunctionCalls++ > 0)
755 			return;
756 
757 		/* loads default content types */
758 		SetStreamOutputContentType("values", new ValuesContentTypeReader);
759 		SetStreamOutputContentType("motion", new MotionContentTypeReader);
760 	}
761 	/*deallocation of all content types in streamOutputContentTypeMap - called by mbpar.cc*/
DestroyStreamOutputContentTypes(void)762 	void DestroyStreamOutputContentTypes(void){
763 		if (streamOutputInitFunctionCalls == 0) {
764 			silent_cerr("DestroyStreamOutputContentTypes() called once too many" << std::endl);
765 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
766 		}
767 
768 		if (--streamOutputInitFunctionCalls > 0) {
769 			return;
770 		}
771 
772 		/* empties all of the content types contained in streamOutputContentTypeMap*/
773 		for (StreamOutputContentTypeMap::iterator i = streamOutputContentTypeMap.begin(); i != streamOutputContentTypeMap.end(); ++i) {
774 			delete i->second;
775 		}
776 		streamOutputContentTypeMap.clear();
777 	}
778