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