1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/output.h,v 1.65 2017/05/29 17:50:43 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 * ACKNOWLEDGEMENTS:
33 * Support for output with NetCDF is based on a contribution
34 * by Patrick Rix <patrick.rix@online.de>
35 */
36
37 /* gestore dell'output */
38
39 #ifndef OUTPUT_H
40 #define OUTPUT_H
41
42 /* se #define DEBUG_COUT l'output avviene su cout anziche' nei files */
43
44 #include <iostream>
45 #include <iomanip>
46 #include <fstream>
47 #include <vector>
48 #include <typeinfo>
49
50 #ifdef USE_NETCDF
51 #if defined(HAVE_NETCDFCPP_H)
52 #include <netcdfcpp.h>
53 #elif defined(HAVE_NETCDF_H)
54 #include <netcdf.h>
55 #endif
56 #endif /* USE_NETCDF */
57
58 #include "myassert.h"
59 #include "except.h"
60 #include "solman.h"
61 #include "filename.h"
62
63 /* OutputHandler - begin */
64
65 class OutputHandler : public FileName {
66 public:
67 enum OutFiles {
68 UNKNOWN = -1,
69 FIRSTFILE = 0,
70 OUTPUT = 0, // 0
71 STRNODES,
72 ELECTRIC,
73 ABSTRACT,
74 INERTIA,
75 JOINTS, // 5
76 FORCES,
77 BEAMS,
78 ROTORS,
79 RESTART,
80 RESTARTXSOL, // 10
81 AERODYNAMIC,
82 HYDRAULIC,
83 PRESNODES,
84 LOADABLE,
85 GENELS, // 15
86 PARTITION,
87 AEROMODALS,
88 REFERENCEFRAMES,
89 LOG,
90 AIRPROPS, // 20
91 PARAMETERS,
92 EXTERNALS,
93 MODAL,
94 NETCDF,
95 THERMALNODES, // 25
96 THERMALELEMENTS,
97 PLATES,
98 GRAVITY,
99 DOFSTATS,
100 DRIVECALLERS, // 30
101 TRACES,
102 EIGENANALYSIS, // NOTE: ALWAYS LAST!
103 LASTFILE // 33
104 };
105
106 private:
107 long currentStep;
108
109 public:
SetCurrentStep(long Step)110 inline void SetCurrentStep(long Step) {
111 currentStep = Step;
112 };
IncCurrentStep(void)113 inline void IncCurrentStep(void) {
114 currentStep++;
115 };
GetCurrentStep(void)116 inline long GetCurrentStep(void) const {
117 return currentStep;
118 };
119
120 private:
121
122 // flag values
123 enum {
124 OUTPUT_NONE = 0x00U,
125 OUTPUT_USE_DEFAULT_PRECISION = 0x01U,
126 OUTPUT_USE_SCIENTIFIC = 0x02U,
127
128 OUTPUT_MAY_USE_TEXT = 0x10U,
129 OUTPUT_USE_TEXT = 0x20U,
130 OUTPUT_MAY_USE_NETCDF = 0x40U,
131 OUTPUT_USE_NETCDF = 0x80U,
132
133 LAST
134 };
135
136 /* Aggiungere qui i files che si desidera avere a disposizione */
137 struct {
138 std::ofstream* pof;
139 unsigned flags;
140 } OutData[LASTFILE];
141
142 // NetCDF dimensions and global attributes related to the binary file
143 #ifdef USE_NETCDF
144 const NcDim *m_DimTime;
145 const NcDim *m_DimV1;
146 const NcDim *m_DimV3;
147 NcFile *m_pBinFile; /* ! one ! binary NetCDF data file */
148 #endif /* USE_NETCDF */
149
150 /* handlers to streams */
151 std::ofstream ofOutput; /* 0 */
152 std::ofstream ofStrNodes;
153 std::ofstream ofElectric;
154 std::ofstream ofAbstract;
155 std::ofstream ofInertia;
156 std::ofstream ofJoints; /* 5 */
157 std::ofstream ofForces;
158 std::ofstream ofBeams;
159 std::ofstream ofRotors;
160 std::ofstream ofRestart;
161 std::ofstream ofRestartXSol; /* 10 */
162 std::ofstream ofAerodynamic;
163 std::ofstream ofHydraulic;
164 std::ofstream ofPresNodes;
165 std::ofstream ofLoadable;
166 std::ofstream ofGenels; /* 15 */
167 std::ofstream ofPartition;
168 std::ofstream ofAeroModals;
169 std::ofstream ofReferenceFrames; /* 20 */
170 std::ofstream ofLog;
171 std::ofstream ofAirProps;
172 std::ofstream ofParameters;
173 std::ofstream ofExternals;
174 std::ofstream ofModal; /* 25 */
175 std::ofstream ofThermalNodes;
176 std::ofstream ofThermalElements;
177 std::ofstream ofPlates;
178 std::ofstream ofGravity;
179 std::ofstream ofDofStats; /* 30 */
180 std::ofstream ofDriveCallers;
181 std::ofstream ofTraces;
182 std::ofstream ofEigenanalysis;
183
184 int iCurrWidth;
185 int iCurrPrecision;
186 int nCurrRestartFile;
187
188 // private because we know we're using valid out index
189 bool IsOpen(int out) const;
190 bool UseDefaultPrecision(int out) const;
191 bool UseScientific(int out) const;
192
193 bool UseText(int out) const;
194 bool UseNetCDF(int out) const;
195
196 // Pseudo-constructor
197 void OutputHandler_int(void);
198
199 public:
200 OutputHandler(void);
201
202 OutputHandler(const char* sFName, int iExtNum = -1);
203
204 void Init(const char* sFName, int iExtNum = -1);
205
206 virtual ~OutputHandler(void);
207
208 /* Aggiungere qui le funzioni che aprono i singoli stream */
209 bool Open(const OutputHandler::OutFiles out);
210
211 /* Overload for eigenanalysis text output */
212 bool Open(const int out, const std::string& postfix);
213 bool IsOpen(const OutputHandler::OutFiles out) const;
214 bool UseDefaultPrecision(const OutputHandler::OutFiles out) const;
215 bool UseScientific(const OutputHandler::OutFiles out) const;
216
217 void SetText(const OutputHandler::OutFiles out);
218 void ClearText(void);
219 void ClearText(const OutputHandler::OutFiles out);
220 bool UseText(const OutputHandler::OutFiles out) const;
221
222 void SetNetCDF(const OutputHandler::OutFiles out);
223 void ClearNetCDF(void);
224 void ClearNetCDF(const OutputHandler::OutFiles out);
225 bool UseNetCDF(const OutputHandler::OutFiles out) const;
226
227 bool Close(const OutputHandler::OutFiles out);
228
229 bool OutputOpen(void);
230 bool RestartOpen(bool openResXSol = false);
231
232 bool PartitionOpen(void);
233 bool LogOpen(void);
234
235 /* Aggiungere qui le funzioni che ritornano gli stream desiderati */
236 inline std::ostream& Get(const OutputHandler::OutFiles f);
237
238 inline std::ostream& Output(void) const;
239 inline std::ostream& StrNodes(void) const;
240 inline std::ostream& Electric(void) const;
241 inline std::ostream& Abstract(void) const;
242 inline std::ostream& Inertia(void) const;
243 inline std::ostream& Joints(void) const;
244 inline std::ostream& Forces(void) const;
245 inline std::ostream& Beams(void) const;
246 inline std::ostream& Rotors(void) const;
247 inline std::ostream& Restart(void) const;
248 inline std::ostream& RestartXSol(void) const;
249 inline std::ostream& Aerodynamic(void) const;
250 inline std::ostream& Hydraulic(void) const;
251 inline std::ostream& PresNodes(void) const;
252 inline std::ostream& Loadable(void) const;
253 inline std::ostream& Genels(void) const;
254 inline std::ostream& Partition(void) const;
255 inline std::ostream& AeroModals(void) const;
256 inline std::ostream& ReferenceFrames(void) const;
257 inline std::ostream& Log(void) const;
258 inline std::ostream& AirProps(void) const;
259 inline std::ostream& Parameters(void) const;
260 inline std::ostream& Externals(void) const;
261 inline std::ostream& Modal(void) const;
262 inline std::ostream& ThermalNodes(void) const;
263 inline std::ostream& ThermalElements(void) const;
264 inline std::ostream& Plates(void) const;
265 inline std::ostream& Gravity(void) const;
266 inline std::ostream& DofStats(void) const;
267 inline std::ostream& DriveCallers(void) const;
268 inline std::ostream& Traces(void) const;
269 inline std::ostream& Eigenanalysis(void) const;
270
271 inline int iW(void) const;
272 inline int iP(void) const;
273
274 void SetWidth(int iNewWidth);
275 void SetPrecision(int iNewPrecision);
276 void SetExceptions(std::ios::iostate flags);
277
278 #ifdef USE_NETCDF
279 inline NcFile* pGetBinFile(void) const;
280
281 struct AttrVal {
282 std::string attr;
283 std::string val;
AttrValAttrVal284 AttrVal(void) { NO_OP; };
AttrValAttrVal285 AttrVal(const std::string& attr, const std::string& val) : attr(attr), val(val) { NO_OP; };
286 };
287
288 typedef std::vector<OutputHandler::AttrVal> AttrValVec;
289 typedef std::vector<const NcDim *> NcDimVec;
290
291 const NcDim *
292 CreateDim(const std::string& name, integer size = -1);
293
294 const NcDim *
295 GetDim(const std::string& name) const;
296
297 inline const NcDim* DimTime(void) const;
298 inline const NcDim* DimV1(void) const;
299 inline const NcDim* DimV3(void) const;
300
301 NcVar *
302 CreateVar(const std::string& name, NcType type,
303 const AttrValVec& attrs, const NcDimVec& dims);
304
305 NcVar *
306 CreateVar(const std::string& name, const std::string& type);
307
308 template <class T>
309 NcVar *
310 CreateVar(const std::string& name,
311 const std::string& units, const std::string& description);
312
313 NcVar *
314 CreateRotationVar(const std::string& name_prefix,
315 const std::string& name_postfix,
316 OrientationDescription od,
317 const std::string& description);
318 #endif /* USE_NETCDF */
319 }; /* End class OutputHandler */
320
321 #ifdef USE_NETCDF
322 template <class T>
323 NcVar *
CreateVar(const std::string & name,const std::string & units,const std::string & description)324 OutputHandler::CreateVar(const std::string& name,
325 const std::string& units, const std::string& description)
326 {
327 AttrValVec attrs(3);
328 NcDimVec dims(1);
329
330 attrs[0] = AttrVal("units", units);
331 attrs[2] = AttrVal("description", description);
332 dims[0] = DimTime();
333
334 NcType type;
335 if (typeid(T) == typeid(integer)) {
336 attrs[1] = AttrVal("type", "integer");
337 type = ncLong;
338
339 } else if (typeid(T) == typeid(doublereal)) {
340 attrs[1] = AttrVal("type", "doublereal");
341 type = ncDouble;
342
343 } else if (typeid(T) == typeid(Vec3)) {
344 attrs[1] = AttrVal("type", "Vec3");
345 dims.resize(2);
346 dims[1] = DimV3();
347 type = ncDouble;
348
349 } else {
350 throw ErrGeneric(MBDYN_EXCEPT_ARGS);
351 }
352
353 return CreateVar(name, type, attrs, dims);
354 }
355
356 inline NcFile *
pGetBinFile(void)357 OutputHandler::pGetBinFile(void) const
358 {
359 return m_pBinFile;
360 }
361
362 inline const NcDim *
DimTime(void)363 OutputHandler::DimTime(void) const
364 {
365 return m_DimTime;
366 }
367
368 inline const NcDim *
DimV1(void)369 OutputHandler::DimV1(void) const
370 {
371 return m_DimV1;
372 }
373
374 inline const NcDim *
DimV3(void)375 OutputHandler::DimV3(void) const
376 {
377 return m_DimV3;
378 }
379 #endif /* USE_NETCDF */
380
381 inline std::ostream&
Get(const OutputHandler::OutFiles f)382 OutputHandler::Get(const OutputHandler::OutFiles f)
383 {
384 ASSERT(f > -1 && f < LASTFILE);
385 ASSERT(IsOpen(f));
386 return *(OutData[f].pof);
387 }
388
389 inline std::ostream&
Output(void)390 OutputHandler::Output(void) const
391 {
392 #ifdef DEBUG_COUT
393 return const_cast<std::ostream &>(cout);
394 #else
395 ASSERT(IsOpen(OUTPUT));
396 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofOutput));
397 #endif
398 }
399
400 inline std::ostream&
StrNodes(void)401 OutputHandler::StrNodes(void) const
402 {
403 ASSERT(IsOpen(STRNODES));
404 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofStrNodes));
405 }
406
407 inline std::ostream&
Electric(void)408 OutputHandler::Electric(void) const
409 {
410 ASSERT(IsOpen(ELECTRIC));
411 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofElectric));
412 }
413
414 inline std::ostream&
ThermalNodes(void)415 OutputHandler::ThermalNodes(void) const
416 {
417 ASSERT(IsOpen(THERMALNODES));
418 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofThermalNodes));
419 }
420
421 inline std::ostream&
ThermalElements(void)422 OutputHandler::ThermalElements(void) const
423 {
424 ASSERT(IsOpen(THERMALELEMENTS));
425 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofThermalElements));
426 }
427
428 inline std::ostream&
Abstract(void)429 OutputHandler::Abstract(void) const
430 {
431 ASSERT(IsOpen(ABSTRACT));
432 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofAbstract));
433 }
434
435 inline std::ostream&
Inertia(void)436 OutputHandler::Inertia(void) const
437 {
438 ASSERT(IsOpen(INERTIA));
439 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofInertia));
440 }
441
442 inline std::ostream&
Joints(void)443 OutputHandler::Joints(void) const
444 {
445 ASSERT(IsOpen(JOINTS));
446 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofJoints));
447 }
448
449 inline std::ostream&
Forces(void)450 OutputHandler::Forces(void) const
451 {
452 ASSERT(IsOpen(FORCES));
453 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofForces));
454 }
455
456 inline std::ostream&
Beams(void)457 OutputHandler::Beams(void) const
458 {
459 ASSERT(IsOpen(BEAMS));
460 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofBeams));
461 }
462
463 inline std::ostream&
Rotors(void)464 OutputHandler::Rotors(void) const
465 {
466 ASSERT(IsOpen(ROTORS));
467 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofRotors));
468 }
469
470 inline std::ostream&
Restart(void)471 OutputHandler::Restart(void) const
472 {
473 ASSERT(IsOpen(RESTART));
474 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofRestart));
475 }
476
477 inline std::ostream&
RestartXSol(void)478 OutputHandler::RestartXSol(void) const
479 {
480 ASSERT(IsOpen(RESTART));
481 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofRestartXSol));
482 }
483
484 inline std::ostream&
Aerodynamic(void)485 OutputHandler::Aerodynamic(void) const
486 {
487 ASSERT(IsOpen(AERODYNAMIC));
488 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofAerodynamic));
489 }
490
491 inline std::ostream&
Hydraulic(void)492 OutputHandler::Hydraulic(void) const
493 {
494 ASSERT(IsOpen(HYDRAULIC));
495 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofHydraulic));
496 }
497
498 inline std::ostream&
PresNodes(void)499 OutputHandler::PresNodes(void) const
500 {
501 ASSERT(IsOpen(PRESNODES));
502 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofPresNodes));
503 }
504
505 inline std::ostream&
Loadable(void)506 OutputHandler::Loadable(void) const
507 {
508 ASSERT(IsOpen(LOADABLE));
509 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofLoadable));
510 }
511
512 inline std::ostream&
Genels(void)513 OutputHandler::Genels(void) const
514 {
515 ASSERT(IsOpen(GENELS));
516 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofGenels));
517 }
518
519 inline std::ostream&
Partition(void)520 OutputHandler::Partition(void) const
521 {
522 ASSERT(IsOpen(PARTITION));
523 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofPartition));
524 }
525
526 inline std::ostream&
AeroModals(void)527 OutputHandler::AeroModals(void) const
528 {
529 ASSERT(IsOpen(AEROMODALS));
530 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofAeroModals));
531 }
532
533 inline std::ostream&
ReferenceFrames(void)534 OutputHandler::ReferenceFrames(void) const
535 {
536 ASSERT(IsOpen(REFERENCEFRAMES));
537 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofReferenceFrames));
538 }
539
540 inline std::ostream&
Log(void)541 OutputHandler::Log(void) const
542 {
543 #ifdef DEBUG_COUT
544 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(cout));
545 #else
546 ASSERT(IsOpen(LOG));
547 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofLog));
548 #endif
549 }
550
551 inline std::ostream&
AirProps(void)552 OutputHandler::AirProps(void) const
553 {
554 ASSERT(IsOpen(AIRPROPS));
555 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofAirProps));
556 }
557
558 inline std::ostream&
Parameters(void)559 OutputHandler::Parameters(void) const
560 {
561 ASSERT(IsOpen(PARAMETERS));
562 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofParameters));
563 }
564
565 inline std::ostream&
Externals(void)566 OutputHandler::Externals(void) const
567 {
568 ASSERT(IsOpen(EXTERNALS));
569 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofExternals));
570 }
571
572 inline std::ostream&
Modal(void)573 OutputHandler::Modal(void) const
574 {
575 ASSERT(IsOpen(MODAL));
576 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofModal));
577 }
578
579 inline std::ostream&
Plates(void)580 OutputHandler::Plates(void) const
581 {
582 ASSERT(IsOpen(PLATES));
583 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofPlates));
584 }
585
586 inline std::ostream&
Gravity(void)587 OutputHandler::Gravity(void) const
588 {
589 ASSERT(IsOpen(GRAVITY));
590 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofGravity));
591 }
592
593 inline std::ostream&
DofStats(void)594 OutputHandler::DofStats(void) const
595 {
596 ASSERT(IsOpen(DOFSTATS));
597 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofDofStats));
598 }
599
600 inline std::ostream&
DriveCallers(void)601 OutputHandler::DriveCallers(void) const
602 {
603 ASSERT(IsOpen(DRIVECALLERS));
604 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofDriveCallers));
605 }
606
607 inline std::ostream&
Traces(void)608 OutputHandler::Traces(void) const
609 {
610 ASSERT(IsOpen(TRACES));
611 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofTraces));
612 }
613
614 inline std::ostream&
Eigenanalysis(void)615 OutputHandler::Eigenanalysis(void) const
616 {
617 ASSERT(IsOpen(EIGENANALYSIS));
618 return const_cast<std::ostream &>(dynamic_cast<const std::ostream &>(ofEigenanalysis));
619 }
620
621
622 inline int
iW(void)623 OutputHandler::iW(void) const
624 {
625 return iCurrWidth;
626 }
627
628 inline int
iP(void)629 OutputHandler::iP(void) const
630 {
631 return iCurrPrecision;
632 }
633
634 /* OutputHandler - end */
635
636
637 /* ToBeOutput - begin */
638
639 const flag fDefaultOut = 1;
640
641 class ToBeOutput {
642 public:
643 enum {
644 OUTPUT = 0x1U,
645
646 // use OUTPUT_MASK to isolate public output flags
647 OUTPUT_MASK = 0xFU,
648
649 // reserve values up to OUTPUT_PRIVATE for public use;
650 // reserved output flags can start from OUTPUT_PRIVATE up
651 OUTPUT_PRIVATE = 0x10U,
652
653 // use OUTPUT_PRIVATE_MASK to isolate private output flags
654 OUTPUT_PRIVATE_MASK = ~OUTPUT_MASK
655 };
656
657 protected:
658 flag fOutput;
659
660 public:
661 ToBeOutput(flag fOut = fDefaultOut);
662 virtual ~ToBeOutput(void);
663
664 virtual void OutputPrepare(OutputHandler &OH);
665
666 /* Regular output */
667 virtual void Output(OutputHandler& OH) const;
668
669 /* Output of perturbed solution (modes ...) */
670 virtual void Output(OutputHandler& OH,
671 const VectorHandler& X, const VectorHandler& XP) const;
672
673 virtual flag fToBeOutput(void) const;
674 virtual bool bToBeOutput(void) const;
675 virtual void SetOutputFlag(flag f = flag(1));
676 };
677
678 /* ToBeOutput - end */
679
680 class Traceable {
681 public:
682 enum {
683 TRACE = 0x01U,
684 TRACE_PUBLIC_MASK = 0x0FU,
685 TRACE_PRIVATE = 0x10U,
686 TRACE_PRIVATE_MASK = ~TRACE_PUBLIC_MASK
687 };
688
689 Traceable(flag fTrace = 0);
690 virtual ~Traceable(void);
691
692 virtual void Trace(OutputHandler& OH) const=0;
693 virtual flag fToBeTraced(void) const;
694 virtual void SetTraceFlag(flag f = TRACE);
695
696 private:
697 flag fTrace;
698 };
699
700 #endif /* OUTPUT_H */
701