1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/output.cc,v 1.74 2017/05/29 18:10:33 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 /* gestore dell'output */
33 
34 #include "mbconfig.h"           /* This goes first in every *.c,*.cc file */
35 
36 #include <sstream>
37 
38 #include "output.h"
39 
40 /* OutputHandler - begin */
41 
42 #ifndef OUTPUT_PRECISION
43 #define OUTPUT_PRECISION 6
44 #endif /* OUTPUT_PRECISION */
45 
46 const int iDefaultWidth = OUTPUT_PRECISION + 6;
47 const int iDefaultPrecision = OUTPUT_PRECISION;
48 
49 const char* psExt[] = {
50 	".out",		//  0
51 	".mov",
52 	".ele",
53 	".abs",
54 	".ine",
55 	".jnt",		//  5
56 	".frc",
57 	".act",
58 	".rot",
59 	".rst",
60 	".rst.X",	// 10
61 	".aer",
62 	".hyd",
63 	".prs",
64 	".usr",
65 	".gen",		// 15
66 	".par",
67 	".amd",
68 	".rfm",
69 	".log",
70 	".air",		// 20
71 	".prm",
72 	".ext",
73 	".mod",
74 	".nc",
75 	".thn",		// 25
76 	".the",
77 	".pla",
78 	".grv",
79 	".dof",
80 	".drv",		// 30
81 	".trc",
82 	".m",		// NOTE: ALWAYS LAST!
83 	NULL		// 33
84 };
85 
86 /* Costruttore senza inizializzazione */
OutputHandler(void)87 OutputHandler::OutputHandler(void)
88 : FileName(NULL),
89 #ifdef USE_NETCDF
90 m_DimTime(0),
91 m_DimV1(0),
92 m_DimV3(0),
93 m_pBinFile(0),
94 #endif /* USE_NETCDF */
95 iCurrWidth(iDefaultWidth),
96 iCurrPrecision(iDefaultPrecision),
97 nCurrRestartFile(0)
98 {
99 	OutputHandler_int();
100 }
101 
102 /* Costruttore con inizializzazione */
OutputHandler(const char * sFName,int iExtNum)103 OutputHandler::OutputHandler(const char* sFName, int iExtNum)
104 : FileName(sFName, iExtNum),
105 #ifdef USE_NETCDF
106 m_DimTime(0),
107 m_DimV1(0),
108 m_DimV3(0),
109 m_pBinFile(0),
110 #endif /* USE_NETCDF */
111 iCurrWidth(iDefaultWidth),
112 iCurrPrecision(iDefaultPrecision),
113 nCurrRestartFile(0)
114 {
115 	OutputHandler_int();
116 	Init(sFName, iExtNum);
117 }
118 
119 // Pesudo-constructor
120 void
OutputHandler_int(void)121 OutputHandler::OutputHandler_int(void)
122 {
123 	OutData[OUTPUT].flags = OUTPUT_USE_DEFAULT_PRECISION
124 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
125 	OutData[OUTPUT].pof = &ofOutput;
126 
127 	OutData[STRNODES].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
128 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT
129 		| OUTPUT_MAY_USE_NETCDF;
130 	OutData[STRNODES].pof = &ofStrNodes;
131 
132 	OutData[ELECTRIC].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
133 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
134 	OutData[ELECTRIC].pof= &ofElectric;
135 
136 	OutData[THERMALNODES].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
137 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
138 	OutData[THERMALNODES].pof= &ofThermalNodes;
139 
140 	OutData[THERMALELEMENTS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
141 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
142 	OutData[THERMALELEMENTS].pof= &ofThermalElements;
143 
144 	OutData[ABSTRACT].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
145 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
146 	OutData[ABSTRACT].pof = &ofAbstract;
147 
148 	OutData[INERTIA].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
149 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT
150 		| OUTPUT_MAY_USE_NETCDF;
151 	OutData[INERTIA].pof = &ofInertia;
152 
153 	OutData[JOINTS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
154 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT
155 		| OUTPUT_MAY_USE_NETCDF;
156 	OutData[JOINTS].pof = &ofJoints;
157 
158 	OutData[FORCES].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
159 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT
160 		| OUTPUT_MAY_USE_NETCDF;
161 	OutData[FORCES].pof = &ofForces;
162 
163 	OutData[BEAMS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
164 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT
165 		| OUTPUT_MAY_USE_NETCDF;
166 	OutData[BEAMS].pof = &ofBeams;
167 
168 	OutData[ROTORS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
169 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
170 	OutData[ROTORS].pof = &ofRotors;
171 
172 	OutData[RESTART].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
173 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
174 	OutData[RESTART].pof = &ofRestart;
175 
176 	OutData[RESTARTXSOL].flags = 0
177 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
178 	OutData[RESTARTXSOL].pof = &ofRestartXSol;
179 
180 	OutData[AERODYNAMIC].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
181 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT
182 		| OUTPUT_MAY_USE_NETCDF;
183 	OutData[AERODYNAMIC].pof = &ofAerodynamic;
184 
185 	OutData[HYDRAULIC].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
186 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
187 	OutData[HYDRAULIC].pof = &ofHydraulic;
188 
189 	OutData[PRESNODES].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
190 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
191 	OutData[PRESNODES].pof = &ofPresNodes;
192 
193 	OutData[LOADABLE].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
194 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT
195 		| OUTPUT_MAY_USE_NETCDF;
196 	OutData[LOADABLE].pof = &ofLoadable;
197 
198 	OutData[GENELS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
199 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
200 	OutData[GENELS].pof = &ofGenels;
201 
202 	OutData[PARTITION].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
203 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
204 	OutData[PARTITION].pof = &ofPartition;
205 
206 	OutData[AEROMODALS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
207 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
208 	OutData[AEROMODALS].pof = &ofAeroModals;
209 
210 	OutData[REFERENCEFRAMES].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
211 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
212 	OutData[REFERENCEFRAMES].pof = &ofReferenceFrames;
213 
214 	OutData[LOG].flags = 0
215 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
216 	OutData[LOG].pof = &ofLog;
217 
218 	OutData[AIRPROPS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
219 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
220 	OutData[AIRPROPS].pof = &ofAirProps;
221 
222 	OutData[PARAMETERS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
223 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
224 	OutData[PARAMETERS].pof = &ofParameters;
225 
226 	OutData[EXTERNALS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
227 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
228 	OutData[EXTERNALS].pof = &ofExternals;
229 
230 	OutData[MODAL].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
231 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
232 	OutData[MODAL].pof = &ofModal;
233 
234 	OutData[PLATES].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
235 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT
236 		| OUTPUT_MAY_USE_NETCDF;
237 	OutData[PLATES].pof = &ofPlates;
238 
239 	OutData[GRAVITY].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
240 		| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
241 	OutData[GRAVITY].pof = &ofGravity;
242 
243 	OutData[DOFSTATS].flags = OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
244 	OutData[DOFSTATS].pof = &ofDofStats;
245 
246 	OutData[DRIVECALLERS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
247 			| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
248 	OutData[DRIVECALLERS].pof = &ofDriveCallers;
249 
250 	OutData[TRACES].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
251 			| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
252 	OutData[TRACES].pof = &ofTraces;
253 
254 	OutData[EIGENANALYSIS].flags = OUTPUT_USE_DEFAULT_PRECISION | OUTPUT_USE_SCIENTIFIC
255 			| OUTPUT_MAY_USE_TEXT | OUTPUT_USE_TEXT;
256 	OutData[EIGENANALYSIS].pof = &ofEigenanalysis;
257 
258 	OutData[NETCDF].flags = 0
259 		| OUTPUT_MAY_USE_NETCDF;
260 	OutData[NETCDF].pof = 0;
261 
262 	currentStep = 0;
263 }
264 
265 /* Inizializzazione */
266 void
Init(const char * sFName,int iExtNum)267 OutputHandler::Init(const char* sFName, int iExtNum)
268 {
269 	FileName::iInit(sFName, iExtNum);
270 
271 	OutputOpen();
272 	LogOpen();
273 }
274 
275 /* Distruttore */
~OutputHandler(void)276 OutputHandler::~OutputHandler(void)
277 {
278 	for (int iCnt = 0; iCnt < LASTFILE; iCnt++) {
279 		if (IsOpen(iCnt)) {
280 #ifdef USE_NETCDF
281 			if (iCnt == NETCDF) {
282 				if (m_pBinFile != 0) {
283 					delete m_pBinFile;
284 				}
285 
286 			} else
287 #endif /* USE_NETCDF */
288 			{
289 				OutData[iCnt].pof->exceptions(std::ios::iostate(0));
290 				OutData[iCnt].pof->close();
291 			}
292 		}
293 	}
294 }
295 
296 /* Aggiungere qui le funzioni che aprono i singoli stream */
297 bool
Open(const OutputHandler::OutFiles out)298 OutputHandler::Open(const OutputHandler::OutFiles out)
299 {
300 #ifdef USE_NETCDF
301 	if (out == NETCDF && !IsOpen(out)) {
302 		m_pBinFile = new NcFile(_sPutExt((char*)(psExt[NETCDF])), NcFile::Replace);
303 		m_pBinFile->set_fill(NcFile::Fill);
304 
305          	if (!m_pBinFile->is_valid()) {
306 			silent_cerr("NetCDF file is invalid" << std::endl);
307 			throw ErrFile(MBDYN_EXCEPT_ARGS);
308 		}
309 
310 		// Let's define some dimensions which could be useful
311 		m_DimTime = CreateDim("time");
312 		m_DimV1 = CreateDim("vec1", 1);
313 		m_DimV3 = CreateDim("vec3", 3);
314 
315 	} else
316 #endif /* USE_NETCDF */
317 	{
318 		if (!IsOpen(out)) {
319 			const char *fname = _sPutExt(psExt[out]);
320 
321 			// Apre lo stream
322 			OutData[out].pof->open(fname);
323 
324 			if (!(*OutData[out].pof)) {
325 				silent_cerr("Unable to open file "
326 					"\"" << fname << "\"" << std::endl);
327 				throw ErrFile(MBDYN_EXCEPT_ARGS);
328 			}
329 
330 			if (UseText(out)) {
331 				// Setta la formattazione dei campi
332 				if (UseDefaultPrecision(out)) {
333 					OutData[out].pof->precision(iCurrPrecision);
334 				}
335 
336 				// Setta la notazione
337 				if (UseScientific(out)) {
338 					OutData[out].pof->setf(std::ios::scientific);
339 				}
340 			}
341 		}
342 
343 		return true;
344 	}
345 
346 	return false;
347 }
348 
349 bool
Open(const int out,const std::string & postfix)350 OutputHandler::Open(const int out, const std::string& postfix)
351 {
352 	if (UseText(out) && !IsOpen(out)) {
353 		std::string sCurrFileName = sGet();
354 		std::stringstream fname_ss;
355 
356 		unsigned uExtIdx = sCurrFileName.find_last_of(EXT_SEP);
357 
358 		if (uExtIdx != std::string::npos) {
359 			fname_ss << sCurrFileName.substr(0, uExtIdx);
360 
361 		} else {
362 			fname_ss << sCurrFileName;
363 		}
364 
365 		fname_ss << postfix << psExt[out] << std::ends;
366 
367 		const std::string fname = fname_ss.str();
368 
369 		// Opens the stream
370 		OutData[out].pof->open(fname.c_str());
371 
372 		if (!(*OutData[out].pof)) {
373 			silent_cerr("Unable to open file "
374 				"\"" << fname << "\"" << std::endl);
375 			throw ErrFile(MBDYN_EXCEPT_ARGS);
376 		}
377 
378 		// Sets the field format
379 		if (UseDefaultPrecision(out)) {
380 			OutData[out].pof->precision(iCurrPrecision);
381 		}
382 
383 		// Sets the notation
384 		if (UseScientific(out)) {
385 			OutData[out].pof->setf(std::ios::scientific);
386 		}
387 
388 		return true;
389 	}
390 
391 	return false;
392 }
393 
394 bool
IsOpen(int out) const395 OutputHandler::IsOpen(int out) const
396 {
397 	ASSERT(out > OutputHandler::UNKNOWN);
398 	ASSERT(out < OutputHandler::LASTFILE);
399 
400 	return IsOpen(OutputHandler::OutFiles(out));
401 }
402 
403 bool
IsOpen(const OutputHandler::OutFiles out) const404 OutputHandler::IsOpen(const OutputHandler::OutFiles out) const
405 {
406 #ifdef USE_NETCDF
407 	if (out == NETCDF) {
408 		return m_pBinFile == 0 ? false : m_pBinFile->is_valid();
409 	}
410 #endif /* USE_NETCDF */
411 
412 	return OutData[out].pof == 0 ? false : OutData[out].pof->is_open();
413 }
414 
415 bool
UseScientific(int out) const416 OutputHandler::UseScientific(int out) const
417 {
418 	ASSERT(out > OutputHandler::UNKNOWN);
419 	ASSERT(out < OutputHandler::LASTFILE);
420 
421 	return UseScientific(OutputHandler::OutFiles(out));
422 }
423 
424 bool
UseScientific(const OutputHandler::OutFiles out) const425 OutputHandler::UseScientific(const OutputHandler::OutFiles out) const
426 {
427 	return (OutData[out].flags & OUTPUT_USE_SCIENTIFIC);
428 }
429 
430 bool
UseDefaultPrecision(int out) const431 OutputHandler::UseDefaultPrecision(int out) const
432 {
433 	ASSERT(out > OutputHandler::UNKNOWN);
434 	ASSERT(out < OutputHandler::LASTFILE);
435 
436 	return UseDefaultPrecision(OutputHandler::OutFiles(out));
437 }
438 
439 bool
UseDefaultPrecision(const OutputHandler::OutFiles out) const440 OutputHandler::UseDefaultPrecision(const OutputHandler::OutFiles out) const
441 {
442 	return (OutData[out].flags & OUTPUT_USE_DEFAULT_PRECISION);
443 }
444 
445 bool
UseText(int out) const446 OutputHandler::UseText(int out) const
447 {
448 	ASSERT(out > OutputHandler::UNKNOWN);
449 	ASSERT(out < OutputHandler::LASTFILE);
450 
451 	return UseText(OutputHandler::OutFiles(out));
452 }
453 
454 void
SetText(const OutputHandler::OutFiles out)455 OutputHandler::SetText(const OutputHandler::OutFiles out)
456 {
457 	if (!(OutData[out].flags & OUTPUT_MAY_USE_TEXT)) {
458 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
459 	}
460 
461 	OutData[out].flags |= OUTPUT_USE_TEXT;
462 }
463 
464 void
ClearText(void)465 OutputHandler::ClearText(void)
466 {
467 	for (int out = FIRSTFILE; out < LASTFILE; out++) {
468 		if (OutData[out].flags & OUTPUT_MAY_USE_TEXT) {
469 			OutData[out].flags &= ~OUTPUT_USE_TEXT;
470 		}
471 	}
472 }
473 
474 void
ClearText(const OutputHandler::OutFiles out)475 OutputHandler::ClearText(const OutputHandler::OutFiles out)
476 {
477 	if (!(OutData[out].flags & OUTPUT_MAY_USE_TEXT)) {
478 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
479 	}
480 
481 	OutData[out].flags &= ~OUTPUT_USE_TEXT;
482 }
483 
484 bool
UseText(const OutputHandler::OutFiles out) const485 OutputHandler::UseText(const OutputHandler::OutFiles out) const
486 {
487 	return (OutData[out].flags & OUTPUT_USE_TEXT);
488 }
489 
490 bool
UseNetCDF(int out) const491 OutputHandler::UseNetCDF(int out) const
492 {
493 	ASSERT(out > OutputHandler::UNKNOWN);
494 	ASSERT(out < OutputHandler::LASTFILE);
495 
496 	return UseNetCDF(OutputHandler::OutFiles(out));
497 }
498 
499 void
SetNetCDF(const OutputHandler::OutFiles out)500 OutputHandler::SetNetCDF(const OutputHandler::OutFiles out)
501 {
502 	if (!(OutData[out].flags & OUTPUT_MAY_USE_NETCDF)) {
503 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
504 	}
505 
506 	OutData[out].flags |= OUTPUT_USE_NETCDF;
507 }
508 
509 void
ClearNetCDF(void)510 OutputHandler::ClearNetCDF(void)
511 {
512 	for (int out = FIRSTFILE; out < LASTFILE; out++) {
513 		if (OutData[out].flags & OUTPUT_MAY_USE_NETCDF) {
514 			OutData[out].flags &= ~OUTPUT_USE_NETCDF;
515 		}
516 	}
517 }
518 
519 void
ClearNetCDF(const OutputHandler::OutFiles out)520 OutputHandler::ClearNetCDF(const OutputHandler::OutFiles out)
521 {
522 	if (!(OutData[out].flags & OUTPUT_MAY_USE_NETCDF)) {
523 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
524 	}
525 
526 	OutData[out].flags &= ~OUTPUT_USE_NETCDF;
527 }
528 
529 bool
UseNetCDF(const OutputHandler::OutFiles out) const530 OutputHandler::UseNetCDF(const OutputHandler::OutFiles out) const
531 {
532 	return (OutData[out].flags & OUTPUT_USE_NETCDF);
533 }
534 
535 bool
Close(const OutputHandler::OutFiles out)536 OutputHandler::Close(const OutputHandler::OutFiles out)
537 {
538 	if (!IsOpen(out)) {
539 		return false;
540 	}
541 
542 #ifdef USE_NETCDF
543 	if (out == NETCDF) {
544 		m_pBinFile->close();
545 
546 	} else
547 #endif /* USE_NETCDF */
548 	{
549 		// Chiude lo stream
550 		OutData[out].pof->close();
551 	}
552 
553 	return true;
554 }
555 
556 bool
OutputOpen(void)557 OutputHandler::OutputOpen(void)
558 {
559 	return Open(OUTPUT);
560 }
561 
562 bool
RestartOpen(bool openResXSol)563 OutputHandler::RestartOpen(bool openResXSol)
564 {
565 	if (!IsOpen(RESTART)) {
566 		char *resExt = NULL;
567 		int n = nCurrRestartFile > 0 ?
568 			(int)log10(nCurrRestartFile) + 1 : 1;
569 		int lenExt = STRLENOF(".")
570 			+ n
571 			+ STRLENOF(".rst")
572 			+ 1;
573 
574 		SAFENEWARR(resExt, char, lenExt);
575 		snprintf(resExt, lenExt, ".%.*d.rst", n, nCurrRestartFile);
576 		/* Apre lo stream */
577 	      	OutData[RESTART].pof->open(_sPutExt(resExt));
578 
579 	      	if(!(*OutData[RESTART].pof)) {
580 		 	std::cerr << "Unable to open file '" << _sPutExt(resExt)
581 		   		<< '\'' << std::endl;
582 			throw ErrFile(MBDYN_EXCEPT_ARGS);
583 		}
584 		SAFEDELETEARR(resExt);
585 
586 		/* Setta la formattazione dei campi */
587 		if(UseDefaultPrecision(RESTART)) {
588 			OutData[RESTART].pof->precision(iCurrPrecision);
589 		}
590 
591 		/* Setta la notazione */
592 		if(UseScientific(RESTART)) {
593 			OutData[RESTART].pof->setf(std::ios::scientific);
594 		}
595 
596 		if (openResXSol) {
597 			ASSERT(!IsOpen(RESTARTXSOL));
598 
599 			char *resXSolExt = NULL;
600 			int n = nCurrRestartFile > 0 ?
601 				(int)log10(nCurrRestartFile) + 1 : 1;
602 			int lenXSolExt = STRLENOF(".")
603 				+ n
604 				+ STRLENOF(".rst.X")
605 				+ 1;
606 
607 			SAFENEWARR(resXSolExt, char, lenXSolExt);
608 			snprintf(resXSolExt, lenXSolExt, ".%.*d.rst.X", n, nCurrRestartFile);
609 			/* Apre lo stream */
610 		      	OutData[RESTARTXSOL].pof->open(_sPutExt(resXSolExt));
611 		      	if(!(*OutData[RESTARTXSOL].pof)) {
612 			 	std::cerr << "Unable to open file '" << _sPutExt(resExt)
613 			   		<< '\'' << std::endl;
614 				throw ErrFile(MBDYN_EXCEPT_ARGS);
615 			}
616 			SAFEDELETEARR(resXSolExt);
617 			/* non occorre settare la precisione e il formato
618 			perche' il file e' binario */
619 		}
620 
621 		nCurrRestartFile++;
622 
623  	     	return false;
624 	}
625 
626 	return true;
627 }
628 
629 bool
PartitionOpen(void)630 OutputHandler::PartitionOpen(void)
631 {
632 	ASSERT(!IsOpen(PARTITION));
633 	return Open(PARTITION);
634 }
635 
636 bool
LogOpen(void)637 OutputHandler::LogOpen(void)
638 {
639 	ASSERT(!IsOpen(LOG));
640 	return Open(LOG);
641 }
642 
643 /* Setta precisione e dimensioni campo */
644 const int iWidth = 7; /* Caratteri richiesti dalla notazione esponenziale */
645 
646 void
SetWidth(int iNewWidth)647 OutputHandler::SetWidth(int iNewWidth)
648 {
649 	ASSERT(iNewWidth > iWidth);
650 	if (iNewWidth > iWidth) {
651 		iCurrWidth = iNewWidth;
652 		iCurrPrecision = iCurrWidth-iWidth;
653 		for (int iCnt = 0; iCnt < LASTFILE; iCnt++) {
654 			if (UseDefaultPrecision(iCnt) && IsOpen(iCnt)) {
655 				OutData[iCnt].pof->width(iCurrWidth);
656 				OutData[iCnt].pof->precision(iCurrPrecision);
657 			}
658 		}
659 	}
660 }
661 
662 void
SetPrecision(int iNewPrecision)663 OutputHandler::SetPrecision(int iNewPrecision)
664 {
665 	ASSERT(iNewPrecision > 0);
666 	if (iNewPrecision > 0) {
667 		iCurrPrecision = iNewPrecision;
668 		iCurrWidth = iNewPrecision + iWidth;
669 		for (int iCnt = 0; iCnt < LASTFILE; iCnt++) {
670 			if (UseDefaultPrecision(iCnt) && IsOpen(iCnt)) {
671 				OutData[iCnt].pof->width(iCurrWidth);
672 				OutData[iCnt].pof->precision(iCurrPrecision);
673 			}
674 		}
675 	}
676 }
677 
SetExceptions(std::ios::iostate flags)678 void OutputHandler::SetExceptions(std::ios::iostate flags)
679 {
680 	for (int iCnt = 0; iCnt < LASTFILE; iCnt++) {
681 		if(OutData[iCnt].pof) {
682 			OutData[iCnt].pof->exceptions(flags);
683 		}
684 	}
685 }
686 
687 #ifdef USE_NETCDF
688 const NcDim *
CreateDim(const std::string & name,integer size)689 OutputHandler::CreateDim(const std::string& name, integer size)
690 {
691 	ASSERT(m_pBinFile != 0);
692 
693 	NcDim *dim;
694 	if (size == -1) {
695 		dim = m_pBinFile->add_dim(name.c_str());
696 
697 	} else {
698 		dim = m_pBinFile->add_dim(name.c_str(), size);
699 	}
700 
701 	if (dim == 0) {
702 		std::ostringstream os;
703 		os << "OutputHandler::CreateDim(\"" << name << "\"";
704 		if (size > -1) {
705 			os << ", " << size;
706 		}
707 		os << "): unable to add dimension";
708 		silent_cerr(os.str() << std::endl);
709 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
710 	}
711 
712 	return dim;
713 }
714 
715 const NcDim *
GetDim(const std::string & name) const716 OutputHandler::GetDim(const std::string& name) const
717 {
718 	ASSERT(m_pBinFile != 0);
719 
720 	return m_pBinFile->get_dim(name.c_str());
721 }
722 
723 NcVar *
CreateVar(const std::string & name,NcType type,const AttrValVec & attrs,const NcDimVec & dims)724 OutputHandler::CreateVar(const std::string& name, NcType type,
725 	const AttrValVec& attrs, const NcDimVec& dims)
726 {
727 	NcVar *var;
728 
729 	var = m_pBinFile->add_var(name.c_str(), type, dims.size(), const_cast<const NcDim **>(&dims[0]));
730 	if (var == 0) {
731 		silent_cerr("OutputHandler::CreateVar(\"" << name << "\") failed" << std::endl);
732 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
733 	}
734 
735 	for (AttrValVec::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
736 		if (!var->add_att(i->attr.c_str(), i->val.c_str())) {
737 			silent_cerr("OutputHandler::CreateVar(\"" << name << "\"): "
738 				"add_att(\"" << i->attr << "\", \"" << i->val << "\") failed" << std::endl);
739 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
740 		}
741 	}
742 
743 	return var;
744 }
745 
746 NcVar *
CreateVar(const std::string & name,const std::string & type)747 OutputHandler::CreateVar(const std::string& name, const std::string& type)
748 {
749 	AttrValVec attrs(1);
750 	attrs[0] = AttrVal("type", type);
751 
752 	NcDimVec dims(1);
753 	dims[0] = DimV1();
754 
755 	return CreateVar(name, ncChar, attrs, dims);
756 }
757 
758 NcVar *
CreateRotationVar(const std::string & name_prefix,const std::string & name_postfix,OrientationDescription od,const std::string & description)759 OutputHandler::CreateRotationVar(const std::string& name_prefix,
760 	const std::string& name_postfix,
761 	OrientationDescription od,
762 	const std::string& description)
763 {
764 	NcDimVec dim;
765 	AttrValVec attrs;
766 	std::string name(name_prefix);
767 
768 	switch (od) {
769 	case ORIENTATION_MATRIX:
770 		dim.resize(3);
771 		dim[0] = DimTime();
772 		dim[1] = DimV3();
773 		dim[2] = DimV3();
774 
775 		attrs.resize(3);
776 		attrs[0] = AttrVal("units", "-");
777 		attrs[1] = AttrVal("type", "Mat3x3");
778 		attrs[2] = AttrVal("description",
779 			description + " orientation matrix "
780 			"(R11, R21, R31, R12, R22, R32, R13, R23, R33)");
781 
782 		name += "R";
783 		break;
784 
785 	case ORIENTATION_VECTOR:
786 		dim.resize(2);
787 		dim[0] = DimTime();
788 		dim[1] = DimV3();
789 
790 		attrs.resize(3);
791 		attrs[0] = AttrVal("units", "radian");
792 		attrs[1] = AttrVal("type", "Vec3");
793 		attrs[2] = AttrVal("description",
794 			description + " orientation vector "
795 			"(Phi_X, Phi_Y, Phi_Z)");
796 
797 		name += "Phi";
798 		break;
799 
800 	case EULER_123:
801 	case EULER_313:
802 	case EULER_321:
803 		{
804 		dim.resize(2);
805 		dim[0] = DimTime();
806 		dim[1] = DimV3();
807 
808 		attrs.resize(3);
809 		attrs[0] = AttrVal("units", "radian");
810 		attrs[1] = AttrVal("type", "Vec3");
811 
812 		std::string etype;
813 		switch (od) {
814 		case EULER_123:
815 			etype = "123";
816 			break;
817 
818 		case EULER_313:
819 			etype = "313";
820 			break;
821 
822 		case EULER_321:
823 			etype = "321";
824 			break;
825 
826 		default:
827 			throw ErrGeneric(MBDYN_EXCEPT_ARGS);
828 		}
829 
830 		attrs[2] = AttrVal("description",
831 			description + " orientation Euler angles (" + etype + ") "
832 			"(E_X, E_Y, E_Z)");
833 
834 		name += "E";
835 		} break;
836 
837 	default:
838 		throw ErrGeneric(MBDYN_EXCEPT_ARGS);
839 	}
840 
841 	name += name_postfix;
842 	return CreateVar(name, ncDouble, attrs, dim);
843 }
844 #endif // USE_NETCDF
845 
846 /* OutputHandler - end */
847 
848 
849 /* ToBeOutput - begin */
850 
ToBeOutput(flag fOut)851 ToBeOutput::ToBeOutput(flag fOut)
852 : fOutput(fOut)
853 {
854 	NO_OP;
855 }
856 
~ToBeOutput(void)857 ToBeOutput::~ToBeOutput(void)
858 {
859 	NO_OP;
860 }
861 
862 void
OutputPrepare(OutputHandler & OH)863 ToBeOutput::OutputPrepare(OutputHandler &OH)
864 {
865 	NO_OP;
866 }
867 
868 /* Regular output */
869 void
Output(OutputHandler & OH) const870 ToBeOutput::Output(OutputHandler& OH) const
871 {
872 	NO_OP;
873 }
874 
875 /* Output of perturbed solution (modes ...) */
876 void
Output(OutputHandler & OH,const VectorHandler & X,const VectorHandler & XP) const877 ToBeOutput::Output(OutputHandler& OH,
878 		const VectorHandler& X, const VectorHandler& XP) const
879 {
880 	NO_OP;
881 }
882 
883 flag
fToBeOutput(void) const884 ToBeOutput::fToBeOutput(void) const
885 {
886   	return fOutput;
887 }
888 
889 bool
bToBeOutput(void) const890 ToBeOutput::bToBeOutput(void) const
891 {
892 	return fOutput & flag(1);
893 }
894 
895 void
SetOutputFlag(flag f)896 ToBeOutput::SetOutputFlag(flag f)
897 {
898 	ASSERT(f ? f & flag(1) : 1);
899 
900   	fOutput = f;
901 }
902 
Traceable(flag fTrace)903 Traceable::Traceable(flag fTrace)
904 :fTrace(fTrace)
905 {
906 
907 }
908 
~Traceable(void)909 Traceable::~Traceable(void)
910 {
911 
912 }
913 
fToBeTraced(void) const914 flag Traceable::fToBeTraced(void) const
915 {
916 	return fTrace;
917 }
918 
SetTraceFlag(flag f)919 void Traceable::SetTraceFlag(flag f)
920 {
921 	ASSERT(f ? f & flag(1) : 1);
922 
923 	fTrace = f;
924 }
925 
926 /* ToBeOutput - end */
927