https://mooseframework.inl.gov
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
22 class FormattedTable;
23 class TableValueBase;
24 namespace libMesh
25 {
26 class ExodusII_IO;
27 }
28 
29 template <>
30 void dataStore(std::ostream & stream, FormattedTable & table, void * context);
31 template <>
32 void dataLoad(std::istream & stream, FormattedTable & v, void * context);
33 template <>
34 void dataStore(std::ostream & stream, TableValueBase *& value, void * context);
35 template <>
36 void dataLoad(std::istream & stream, TableValueBase *& value, void * context);
37 
39 {
40 public:
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 
54 std::ostream & operator<<(std::ostream & os, const TableValueBase & value);
55 
56 template <typename T>
57 class TableValue : public TableValueBase
58 {
59 public:
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 
75 private:
76  T _value;
77 };
78 
79 template <>
80 inline void
81 TableValue<bool>::print(std::ostream & os) const
82 {
83  os << (this->_value ? "True" : "False");
84 }
85 
86 template <typename T>
87 void
88 TableValue<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 
95 template <typename T>
96 void
97 TableValue<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 {
111 public:
118  FormattedTable();
119 
124  FormattedTable(const FormattedTable & o);
125 
129  ~FormattedTable();
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();
171 
175  template <typename T = Real>
176  T & getLastData(const std::string & name);
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 
218 
222  void setPrecision(unsigned int precision) { _csv_precision = precision; }
223 
227  void sortColumns();
228 
229 protected:
230  void printTablePiece(std::ostream & out,
231  unsigned int last_n_entries,
232  std::map<std::string, unsigned short> & col_widths,
233  std::vector<std::string>::iterator & col_begin,
234  std::vector<std::string>::iterator & col_end);
235 
236  void printOmittedRow(std::ostream & out,
237  std::map<std::string, unsigned short> & col_widths,
238  std::vector<std::string>::iterator & col_begin,
239  std::vector<std::string>::iterator & col_end) const;
240  void printRowDivider(std::ostream & out,
241  std::map<std::string, unsigned short> & col_widths,
242  std::vector<std::string>::iterator & col_begin,
243  std::vector<std::string>::iterator & col_end) const;
244 
245  void printNoDataRow(char intersect_char,
246  char fill_char,
247  std::ostream & out,
248  std::map<std::string, unsigned short> & col_widths,
249  std::vector<std::string>::iterator & col_begin,
250  std::vector<std::string>::iterator & col_end) const;
251 
258  std::vector<std::pair<Real, std::map<std::string, std::shared_ptr<TableValueBase>>>> _data;
259 
261  std::map<std::string, unsigned int> _align_widths;
262 
264  std::vector<std::string> _column_names;
265 
267  static const unsigned short _column_width;
268 
270  static const unsigned short _min_pps_width;
271 
272 private:
274  void close();
275 
277  void open(const std::string & file_name);
278 
279  void printRow(std::pair<Real, std::map<std::string, std::shared_ptr<TableValueBase>>> & row_data,
280  bool align);
281 
288  void fillEmptyValues(unsigned int last_n_entries = 0);
289 
291  std::string _output_file_name;
292 
294  std::ofstream _output_file;
295 
300  std::size_t _output_row_index;
301 
309 
311  bool _append;
312 
315 
317  std::string _csv_delimiter;
318 
320  unsigned int _csv_precision;
321 
324 
325  friend void
326  dataStore<FormattedTable>(std::ostream & stream, FormattedTable & table, void * context);
327  friend void dataLoad<FormattedTable>(std::istream & stream, FormattedTable & v, void * context);
328 };
329 
330 template <typename T>
331 void
332 FormattedTable::addData(const std::string & name, const T & value)
333 {
334  if (empty())
335  mooseError("No Data stored in the the FormattedTable");
336 
337  auto back_it = _data.rbegin();
338  back_it->second[name] =
339  std::dynamic_pointer_cast<TableValueBase>(std::make_shared<TableValue<T>>(value));
340 
341  if (std::find(_column_names.begin(), _column_names.end(), name) == _column_names.end())
342  {
343  _column_names.push_back(name);
344  _column_names_unsorted = true;
345  }
346 }
347 
348 template <typename T>
349 void
350 FormattedTable::addData(const std::string & name, const T & value, Real time)
351 {
352  auto back_it = _data.rbegin();
353 
354  mooseAssert(back_it == _data.rend() || !MooseUtils::absoluteFuzzyLessThan(time, back_it->first),
355  "Attempting to add data to FormattedTable with the dependent variable in a "
356  "non-increasing order.\nDid you mean to use addData(std::string &, const "
357  "std::vector<Real> &)?");
358 
359  // See if the current "row" is already in the table
360  if (back_it == _data.rend() || !MooseUtils::absoluteFuzzyEqual(time, back_it->first))
361  {
362  _data.emplace_back(time, std::map<std::string, std::shared_ptr<TableValueBase>>());
363  back_it = _data.rbegin();
364  }
365  // Insert or update value
366  back_it->second[name] =
367  std::dynamic_pointer_cast<TableValueBase>(std::make_shared<TableValue<T>>(value));
368 
369  if (std::find(_column_names.begin(), _column_names.end(), name) == _column_names.end())
370  {
371  _column_names.push_back(name);
372  _column_names_unsorted = true;
373  }
374 }
375 
376 template <typename T>
377 void
378 FormattedTable::addData(const std::string & name, const std::vector<T> & vector)
379 {
380  for (MooseIndex(vector) i = 0; i < vector.size(); ++i)
381  {
382  if (i == _data.size())
383  _data.emplace_back(i, std::map<std::string, std::shared_ptr<TableValueBase>>());
384 
385  mooseAssert(MooseUtils::absoluteFuzzyEqual(_data[i].first, i),
386  "Inconsistent indexing in VPP vector");
387 
388  auto & curr_entry = _data[i];
389  curr_entry.second[name] =
390  std::dynamic_pointer_cast<TableValueBase>(std::make_shared<TableValue<T>>(vector[i]));
391  }
392 
393  if (std::find(_column_names.begin(), _column_names.end(), name) == _column_names.end())
394  {
395  _column_names.push_back(name);
396  _column_names_unsorted = true;
397  }
398 }
399 
400 template <typename T>
401 T &
402 FormattedTable::getLastData(const std::string & name)
403 {
404  mooseAssert(!empty(), "No Data stored in the FormattedTable");
405 
406  auto & last_data_map = _data.rbegin()->second;
407  auto it = last_data_map.find(name);
408  if (it == last_data_map.end())
409  mooseError("No Data found for name: " + name);
410 
411  auto value = std::dynamic_pointer_cast<TableValue<T>>(it->second);
412  if (!value)
413  mooseError("Data for ", name, " is not of the requested type.");
414  return value->set();
415 }
416 
417 template <>
418 void dataStore(std::ostream & stream, FormattedTable & table, void * context);
419 template <>
420 void dataLoad(std::istream & stream, FormattedTable & v, void * context);
421 template <>
422 void dataStore(std::ostream & stream, TableValueBase *& value, void * context);
423 template <>
424 void dataLoad(std::istream & stream, TableValueBase *& value, void * context);
void dataLoad(std::istream &stream, FormattedTable &v, void *context)
std::string name(const ElemQuality q)
virtual void print(std::ostream &os) const =0
static constexpr bool isSupportedType()
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether two variables are equal within an absolute tolerance.
Definition: MooseUtils.h:380
~FormattedTable()
The destructor is used to close the file handle.
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)
std::string _output_file_name
The optional output file stream.
std::size_t _output_row_index
Keeps track of the index indicating which vector elements have been output.
void makeGnuplot(const std::string &base_file, const std::string &format)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
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...
void open(const std::string &file_name)
Open or switch the underlying file stream to point to file_name. This is idempotent.
void addData(const std::string &name, const T &value)
Method for adding data to the output table.
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
bool _output_time
Whether or not to output the Time column.
void close()
Close the underlying output file stream if any. This is idempotent.
void printRow(std::pair< Real, std::map< std::string, std::shared_ptr< TableValueBase >>> &row_data, bool align)
void setPrecision(unsigned int precision)
By default printCSV prints output to a precision of 14, this allows this to be changed.
bool _column_names_unsorted
Flag indicating that sorting is necessary (used by sortColumns method).
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
bool empty() const
Returns a boolean value based on whether the FormattedTable contains data or not. ...
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
std::basic_ostream< charT, traits > * os
Definition: InfixIterator.h:33
static void load(std::istream &stream, std::shared_ptr< TableValueBase > &value_base, void *context)
std::string _csv_delimiter
*.csv file delimiter, defaults to ","
TableValue(const T &value)
void fillEmptyValues(unsigned int last_n_entries=0)
Fill any values that are not defined (usually when there are mismatched column lengths) ...
static const unsigned short _min_pps_width
The absolute minimum PPS table width.
void outputTimeColumn(bool output_time)
Set whether or not to output time column.
static MooseEnum getWidthModes()
std::ofstream _output_file
The stream handle (corresponds to _output_file_name)
virtual void print(std::ostream &os) const override
void append(bool append_existing_file)
Sets append mode which means an existing file is not truncated on opening.
std::ostream & operator<<(std::ostream &os, const TableValueBase &value)
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
void dataStore(std::ostream &stream, FormattedTable &table, void *context)
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
virtual void store(std::ostream &stream, void *context) override
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...
bool absoluteFuzzyLessThan(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether a variable is less than another variable within an absolute tolerance...
Definition: MooseUtils.h:475
std::map< std::string, unsigned int > _align_widths
Alignment widths (only used if asked to print aligned to CSV output)
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
This class is used for building, formatting, and outputting tables of numbers.
unsigned int _csv_precision
*.csv file precision, defaults to 14
charT const * delimiter
Definition: InfixIterator.h:34
static const unsigned short _column_width
The single cell width used for all columns in the table.
void writeExodus(libMesh::ExodusII_IO *ex_out, Real time)
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
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.
virtual void store(std::ostream &stream, void *context)=0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< std::string > _column_names
The set of column names updated when data is inserted through the setter methods. ...
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 addRow(Real time)
Force a new row in the table with the passed in time.
virtual ~TableValueBase()=default
void sortColumns()
Sorts columns alphabetically.
void printEnsight(const std::string &file_name)
T & getLastData(const std::string &name)
Retrieve Data for last value of given name.
bool _append
Keeps track of whether we want to open an existing file for appending or overwriting.
void setDelimiter(std::string delimiter)
By default printCSV places "," between each entry, this allows this to be changed.
Real getLastTime()
Retrieve the last time (or independent variable) value.