https://mooseframework.inl.gov
Loading...
Searching...
No Matches
FormattedTable.h
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#pragma once
11
12// MOOSE includes
13#include "Moose.h"
14#include "MooseEnum.h"
15#include "DataIO.h"
16#include "MooseUtils.h"
17
18// C++ includes
19#include <fstream>
20
21// Forward declarations
22class FormattedTable;
23class TableValueBase;
24namespace libMesh
25{
26class ExodusII_IO;
27}
28
29template <>
30void dataStore(std::ostream & stream, FormattedTable & table, void * context);
31template <>
32void dataLoad(std::istream & stream, FormattedTable & v, void * context);
33template <>
34void dataStore(std::ostream & stream, TableValueBase *& value, void * context);
35template <>
36void dataLoad(std::istream & stream, TableValueBase *& value, void * context);
37
39{
40public:
41 virtual ~TableValueBase() = default;
42
43 template <typename T>
44 static constexpr bool isSupportedType()
45 {
46 return std::is_fundamental<T>::value || std::is_same<T, std::string>::value;
47 }
48
49 virtual void print(std::ostream & os) const = 0;
50
51 virtual void store(std::ostream & stream, void * context) = 0;
52};
53
54std::ostream & operator<<(std::ostream & os, const TableValueBase & value);
55
56template <typename T>
58{
59public:
60 TableValue(const T & value) : _value(value)
61 {
62 if (!this->isSupportedType<T>())
63 mooseError("Unsupported type ", MooseUtils::prettyCppType<T>(), " for FormattedTable.");
64 }
65
66 const T & get() const { return _value; }
67 T & set() { return _value; }
68
69 virtual void print(std::ostream & os) const override { os << this->_value; };
70
71 virtual void store(std::ostream & stream, void * context) override;
72 static void
73 load(std::istream & stream, std::shared_ptr<TableValueBase> & value_base, void * context);
74
75private:
77};
78
79template <>
80inline void
81TableValue<bool>::print(std::ostream & os) const
82{
83 os << (this->_value ? "True" : "False");
84}
85
86template <typename T>
87void
88TableValue<T>::store(std::ostream & stream, void * context)
89{
90 std::string type = typeid(T).name();
91 ::dataStore(stream, type, context);
92 ::dataStore(stream, _value, context);
93}
94
95template <typename T>
96void
97TableValue<T>::load(std::istream & stream,
98 std::shared_ptr<TableValueBase> & value_base,
99 void * context)
100{
101 T value;
102 ::dataLoad(stream, value, context);
103 value_base = std::dynamic_pointer_cast<TableValueBase>(std::make_shared<TableValue<T>>(value));
104}
105
110{
111public:
119
125
130
134 bool empty() const;
135
140 void append(bool append_existing_file);
141
145 void addRow(Real time);
146
151 template <typename T = Real>
152 void addData(const std::string & name, const T & value);
153
157 template <typename T = Real>
158 void addData(const std::string & name, const T & value, Real time);
159
164 template <typename T = Real>
165 void addData(const std::string & name, const std::vector<T> & vector);
166
170 Real getLastTime() const;
171
175 template <typename T = Real>
176 T & getLastData(const std::string & name) const;
177
178 void clear();
179
183 void outputTimeColumn(bool output_time) { _output_time = output_time; }
184
185 // const std::map<Real, std::map<std::string, Real>> & getData() const { return _data; }
186
195 void printTable(std::ostream & out, unsigned int last_n_entries = 0);
196 void printTable(std::ostream & out,
197 unsigned int last_n_entries,
198 const MooseEnum & suggested_term_width);
199 void printTable(const std::string & file_name);
200
206 void printCSV(const std::string & file_name, int interval = 1, bool align = false);
207
208 void printEnsight(const std::string & file_name);
209 void writeExodus(libMesh::ExodusII_IO * ex_out, Real time);
210 void makeGnuplot(const std::string & base_file, const std::string & format);
211
212 static MooseEnum getWidthModes();
213
217 void setDelimiter(std::string delimiter) { _csv_delimiter = delimiter; }
218
222 void setPrecision(unsigned int precision) { _csv_precision = precision; }
223
227 void setUseScientificNotation(bool use_scientific_notation)
228 {
229 _csv_use_scientific_notation = use_scientific_notation;
230 }
231
235 void sortColumns();
236
237protected:
238 void printTablePiece(std::ostream & out,
239 unsigned int last_n_entries,
240 std::map<std::string, unsigned short> & col_widths,
241 std::vector<std::string>::iterator & col_begin,
242 std::vector<std::string>::iterator & col_end);
243
244 void printOmittedRow(std::ostream & out,
245 std::map<std::string, unsigned short> & col_widths,
246 std::vector<std::string>::iterator & col_begin,
247 std::vector<std::string>::iterator & col_end) const;
248 void printRowDivider(std::ostream & out,
249 std::map<std::string, unsigned short> & col_widths,
250 std::vector<std::string>::iterator & col_begin,
251 std::vector<std::string>::iterator & col_end) const;
252
253 void printNoDataRow(char intersect_char,
254 char fill_char,
255 std::ostream & out,
256 std::map<std::string, unsigned short> & col_widths,
257 std::vector<std::string>::iterator & col_begin,
258 std::vector<std::string>::iterator & col_end) const;
259
266 std::vector<std::pair<Real, std::map<std::string, std::shared_ptr<TableValueBase>>>> _data;
267
269 std::map<std::string, unsigned int> _align_widths;
270
272 std::vector<std::string> _column_names;
273
275 static const unsigned short _column_width;
276
278 static const unsigned short _min_pps_width;
279
280private:
282 void close();
283
285 void open(const std::string & file_name);
286
287 void printRow(std::pair<Real, std::map<std::string, std::shared_ptr<TableValueBase>>> & row_data,
288 bool align);
289
296 void fillEmptyValues(unsigned int last_n_entries = 0);
297
299 std::string _output_file_name;
300
302 std::ofstream _output_file;
303
308 std::size_t _output_row_index;
309
317
320
323
325 std::string _csv_delimiter;
326
328 unsigned int _csv_precision;
329
332
335
336 friend void
337 dataStore<FormattedTable>(std::ostream & stream, FormattedTable & table, void * context);
338 friend void dataLoad<FormattedTable>(std::istream & stream, FormattedTable & v, void * context);
339};
340
341template <typename T>
342void
343FormattedTable::addData(const std::string & name, const T & value)
344{
345 if (empty())
346 mooseError("No Data stored in the the FormattedTable");
347
348 auto back_it = _data.rbegin();
349 back_it->second[name] =
350 std::dynamic_pointer_cast<TableValueBase>(std::make_shared<TableValue<T>>(value));
351
352 if (std::find(_column_names.begin(), _column_names.end(), name) == _column_names.end())
353 {
354 _column_names.push_back(name);
356 }
357}
358
359template <typename T>
360void
361FormattedTable::addData(const std::string & name, const T & value, Real time)
362{
363 auto back_it = _data.rbegin();
364
365 mooseAssert(back_it == _data.rend() || !MooseUtils::absoluteFuzzyLessThan(time, back_it->first),
366 "Attempting to add data to FormattedTable with the dependent variable in a "
367 "non-increasing order.\nDid you mean to use addData(std::string &, const "
368 "std::vector<Real> &)?");
369
370 // See if the current "row" is already in the table
371 if (back_it == _data.rend() || !MooseUtils::absoluteFuzzyEqual(time, back_it->first))
372 {
373 _data.emplace_back(time, std::map<std::string, std::shared_ptr<TableValueBase>>());
374 back_it = _data.rbegin();
375 }
376 // Insert or update value
377 back_it->second[name] =
378 std::dynamic_pointer_cast<TableValueBase>(std::make_shared<TableValue<T>>(value));
379
380 if (std::find(_column_names.begin(), _column_names.end(), name) == _column_names.end())
381 {
382 _column_names.push_back(name);
384 }
385}
386
387template <typename T>
388void
389FormattedTable::addData(const std::string & name, const std::vector<T> & vector)
390{
391 for (MooseIndex(vector) i = 0; i < vector.size(); ++i)
392 {
393 if (i == _data.size())
394 _data.emplace_back(i, std::map<std::string, std::shared_ptr<TableValueBase>>());
395
396 mooseAssert(MooseUtils::absoluteFuzzyEqual(_data[i].first, i),
397 "Inconsistent indexing in VPP vector");
398
399 auto & curr_entry = _data[i];
400 curr_entry.second[name] =
401 std::dynamic_pointer_cast<TableValueBase>(std::make_shared<TableValue<T>>(vector[i]));
402 }
403
404 if (std::find(_column_names.begin(), _column_names.end(), name) == _column_names.end())
405 {
406 _column_names.push_back(name);
408 }
409}
410
411template <typename T>
412T &
413FormattedTable::getLastData(const std::string & name) const
414{
415 mooseAssert(!empty(), "No Data stored in the FormattedTable");
416
417 auto & last_data_map = _data.rbegin()->second;
418 auto it = last_data_map.find(name);
419 if (it == last_data_map.end())
420 mooseError("No Data found for name: " + name);
421
422 auto value = std::dynamic_pointer_cast<TableValue<T>>(it->second);
423 if (!value)
424 mooseError("Data for ", name, " is not of the requested type.");
425 return value->set();
426}
427
428template <>
429void dataStore(std::ostream & stream, FormattedTable & table, void * context);
430template <>
431void dataLoad(std::istream & stream, FormattedTable & v, void * context);
432template <>
433void dataStore(std::ostream & stream, TableValueBase *& value, void * context);
434template <>
435void dataLoad(std::istream & stream, TableValueBase *& value, void * context);
void dataStore(std::ostream &stream, FormattedTable &table, void *context)
void dataLoad(std::istream &stream, FormattedTable &v, void *context)
std::ostream & operator<<(std::ostream &os, const TableValueBase &value)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
This class is used for building, formatting, and outputting tables of numbers.
static const unsigned short _min_pps_width
The absolute minimum PPS table width.
FormattedTable()
Default constructor - The default constructor takes an optional parameter to turn off stateful printi...
bool _headers_output
Keeps track of whether the header has been output.
void printTablePiece(std::ostream &out, unsigned int last_n_entries, std::map< std::string, unsigned short > &col_widths, std::vector< std::string >::iterator &col_begin, std::vector< std::string >::iterator &col_end)
void setPrecision(unsigned int precision)
By default printCSV prints output to a precision of 14, this allows this to be changed.
static MooseEnum getWidthModes()
void printRow(std::pair< Real, std::map< std::string, std::shared_ptr< TableValueBase > > > &row_data, bool align)
unsigned int _csv_precision
*.csv file precision, defaults to 14
void setUseScientificNotation(bool use_scientific_notation)
Set whether printCSV uses scientific notation for floating point values.
bool _output_time
Whether or not to output the Time column.
static const unsigned short _column_width
The single cell width used for all columns in the table.
bool empty() const
Returns a boolean value based on whether the FormattedTable contains data or not.
void printTable(std::ostream &out, unsigned int last_n_entries=0)
Methods for dumping the table to the stream - either by filename or by stream handle.
std::ofstream _output_file
The stream handle (corresponds to _output_file_name)
void open(const std::string &file_name)
Open or switch the underlying file stream to point to file_name. This is idempotent.
void printCSV(const std::string &file_name, int interval=1, bool align=false)
Method for dumping the table to a csv file - opening and closing the file handle is handled.
bool _append
Keeps track of whether we want to open an existing file for appending or overwriting.
std::string _csv_delimiter
*.csv file delimiter, defaults to ","
void append(bool append_existing_file)
Sets append mode which means an existing file is not truncated on opening.
bool _column_names_unsorted
Flag indicating that sorting is necessary (used by sortColumns method).
void printRowDivider(std::ostream &out, std::map< std::string, unsigned short > &col_widths, std::vector< std::string >::iterator &col_begin, std::vector< std::string >::iterator &col_end) const
std::size_t _output_row_index
Keeps track of the index indicating which vector elements have been output.
void addData(const std::string &name, const T &value)
Method for adding data to the output table.
bool _csv_use_scientific_notation
Whether to print floating point CSV values in scientific notation.
void setDelimiter(std::string delimiter)
By default printCSV places "," between each entry, this allows this to be changed.
T & getLastData(const std::string &name) const
Retrieve Data for last value of given name.
void printEnsight(const std::string &file_name)
~FormattedTable()
The destructor is used to close the file handle.
void printNoDataRow(char intersect_char, char fill_char, std::ostream &out, std::map< std::string, unsigned short > &col_widths, std::vector< std::string >::iterator &col_begin, std::vector< std::string >::iterator &col_end) const
Real getLastTime() const
Retrieve the last time (or independent variable) value.
void writeExodus(libMesh::ExodusII_IO *ex_out, Real time)
void close()
Close the underlying output file stream if any. This is idempotent.
std::map< std::string, unsigned int > _align_widths
Alignment widths (only used if asked to print aligned to CSV output)
void addRow(Real time)
Force a new row in the table with the passed in time.
void makeGnuplot(const std::string &base_file, const std::string &format)
std::vector< std::pair< Real, std::map< std::string, std::shared_ptr< TableValueBase > > > > _data
Data structure for the console table: The first part of the pair tracks the independent variable (nor...
std::string _output_file_name
The optional output file stream.
void sortColumns()
Sorts columns alphabetically.
std::vector< std::string > _column_names
The set of column names updated when data is inserted through the setter methods.
void outputTimeColumn(bool output_time)
Set whether or not to output time column.
void printOmittedRow(std::ostream &out, std::map< std::string, unsigned short > &col_widths, std::vector< std::string >::iterator &col_begin, std::vector< std::string >::iterator &col_end) const
void fillEmptyValues(unsigned int last_n_entries=0)
Fill any values that are not defined (usually when there are mismatched column lengths)
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
static constexpr bool isSupportedType()
virtual void store(std::ostream &stream, void *context)=0
virtual ~TableValueBase()=default
virtual void print(std::ostream &os) const =0
virtual void store(std::ostream &stream, void *context) override
virtual void print(std::ostream &os) const override
static void load(std::istream &stream, std::shared_ptr< TableValueBase > &value_base, void *context)
const T & get() const
TableValue(const T &value)
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...