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() 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 
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 
237 protected:
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 
280 private:
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 
319  bool _append;
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 
341 template <typename T>
342 void
343 FormattedTable::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);
355  _column_names_unsorted = true;
356  }
357 }
358 
359 template <typename T>
360 void
361 FormattedTable::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);
383  _column_names_unsorted = true;
384  }
385 }
386 
387 template <typename T>
388 void
389 FormattedTable::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);
407  _column_names_unsorted = true;
408  }
409 }
410 
411 template <typename T>
412 T &
413 FormattedTable::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 
428 template <>
429 void dataStore(std::ostream & stream, FormattedTable & table, void * context);
430 template <>
431 void dataLoad(std::istream & stream, FormattedTable & v, void * context);
432 template <>
433 void dataStore(std::ostream & stream, TableValueBase *& value, void * context);
434 template <>
435 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()
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
Find a value in an array.
Definition: KokkosUtils.h:40
~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.
bool _csv_use_scientific_notation
Whether to print floating point CSV values in scientific notation.
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:311
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.
void setUseScientificNotation(bool use_scientific_notation)
Set whether printCSV uses scientific notation for floating point values.
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:34
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...
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:54
This class is used for building, formatting, and outputting tables of numbers.
Real getLastTime() const
Retrieve the last time (or independent variable) value.
unsigned int _csv_precision
*.csv file precision, defaults to 14
charT const * delimiter
Definition: InfixIterator.h:35
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)
bool _append
Keeps track of whether we want to open an existing file for appending or overwriting.
T & getLastData(const std::string &name) const
Retrieve Data for last value of given name.
void setDelimiter(std::string delimiter)
By default printCSV places "," between each entry, this allows this to be changed.