From e154fd0be7c8ded1e14ba4d3303f3270932fb161 Mon Sep 17 00:00:00 2001 From: bangerth Date: Mon, 17 Oct 2011 18:26:33 +0000 Subject: [PATCH] Change the inner workings of the TableHandler and derived ConvergenceTable class. git-svn-id: https://svn.dealii.org/trunk@24616 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/doc/news/changes.h | 11 +- deal.II/include/deal.II/base/table_handler.h | 214 ++++++++++--------- deal.II/source/base/table_handler.cc | 160 +++++--------- 3 files changed, 182 insertions(+), 203 deletions(-) diff --git a/deal.II/doc/news/changes.h b/deal.II/doc/news/changes.h index 554a0b1059..f861da34a1 100644 --- a/deal.II/doc/news/changes.h +++ b/deal.II/doc/news/changes.h @@ -36,7 +36,9 @@ inconvenience this causes.
  1. New: parallel::distributed::Triangulation::save()/load() to store the refinement information to disk. Also supports saving solution vectors -using the SolutionTransfer class. (Timo Heister, 2011/10/12) +using the SolutionTransfer class. +
    +(Timo Heister, 2011/10/12)
@@ -46,6 +48,13 @@ using the SolutionTransfer class. (Timo Heister, 2011/10/12)

Specific improvements

    +
  1. Changed: The TableHandler class has been changed significantly internally. +It could previously store arbitrary values (though in practice, only int, unsigned int, +double and std::string were implemented. The class is now restricted to this particular +set of types +
    +(Wolfgang Bangerth, 2011/10/17) +
  2. Fixed: searching in the doxygen documentation.
    (Timo Heister, 2011/10/13) diff --git a/deal.II/include/deal.II/base/table_handler.h b/deal.II/include/deal.II/base/table_handler.h index eb962370fa..04f7d9afb4 100644 --- a/deal.II/include/deal.II/base/table_handler.h +++ b/deal.II/include/deal.II/base/table_handler.h @@ -21,7 +21,6 @@ #include #include -DEAL_II_NAMESPACE_OPEN // we only need output streams, but older compilers did not provide // them in a separate include file #ifdef HAVE_STD_OSTREAM_HEADER @@ -30,89 +29,53 @@ DEAL_II_NAMESPACE_OPEN # include #endif +#include -/** - * Abstract base class for the TableEntry class. See there. - * This class is not to be used by the user. - * - * @ingroup textoutput - * @author Ralf Hartmann, 1999 - */ -class TableEntryBase -{ - public: - /** - * Constructor. - */ - TableEntryBase(); - - /** - * Virtual destructor. - */ - virtual ~TableEntryBase(); - - /** - * Write the table entry as text. - */ - virtual void write_text (std::ostream &) const = 0; - - /** - * Write the table entry in tex format. - */ - virtual void write_tex (std::ostream &) const = 0; -}; +DEAL_II_NAMESPACE_OPEN -/** - * A TableEntry stores the value of a table entry. - * The value type of this table entry is arbitrary. For - * a TableEntry with a non-common value - * type you may want to specialize the output functions in order - * to get nicer output. This class is not to be used by the user. - * - * For more detail see the TableHandler class. - * - * @ingroup textoutput - * @author Ralf Hartmann, 1999 - */ -template -class TableEntry : public TableEntryBase +namespace internal { - public: - /** - * Constructor. - */ - TableEntry (const value_type value); - - /** - * Destructor. - */ - virtual ~TableEntry(); - - /** - * Returns the value of this - * table entry. - */ - value_type value () const; - - /** - * Write the table entry as text. - */ - virtual void write_text (std::ostream &out) const; - - /** - * Write the table entry in tex - * format. - */ - virtual void write_tex (std::ostream &out) const; - - private: - /** - * Stored value. - */ - const value_type val; -}; + /** + * A TableEntry stores the value of a table entry. + * It can either be of type int, unsigned int, double or std::string. + * In essence, this structure is the same as + * boost::variant + * but we wrap this object in a structure for which we can write + * a function that can serialize it. This is also why the function + * is not in fact of type boost::any. + */ + struct TableEntry + { + /** + * Abbreviation for the data type stored by this object. + */ + typedef boost::variant value_type; + + /** + * Return the value stored by this object. The template type + * T must be one of int,unsigned int,double,std::string + * and it must match the data type of the object originally stored + * in this TableEntry object. + */ + template + T get () const; + + /** + * Return the numeric value of this object if data has been stored in + * it either as an integer, an unsigned integer, or a double. + * + * @return double + **/ + double get_numeric_value () const; + + /** + * Stored value. + */ + value_type value; + }; +} /** @@ -177,7 +140,7 @@ class TableEntry : public TableEntryBase * @endcode * * @ingroup textoutput - * @author Ralf Hartmann, 1999 + * @author Ralf Hartmann, 1999; Wolfgang Bangerth, 2011 */ class TableHandler { @@ -392,31 +355,23 @@ class TableHandler /** * Constructor needed by STL maps. */ - Column(); + Column (); /** * Constructor. */ - Column(const std::string &tex_caption); + Column (const std::string &tex_caption); - /** - * Destructor. - */ - ~Column(); /** * List of entries within - * this column. They may - * actually be of very - * different type, since we - * use the templated - * TableEntry class - * for actual values, which - * is only a wrapper for - * T, but is derived from - * TableEntryBase. + * this column. Values are + * always immediately + * converted to strings to + * provide a uniform method + * of lookup. */ - std::vector entries; + std::vector entries; /** * The caption of the column @@ -550,9 +505,74 @@ class TableHandler * The label of the table. */ std::string tex_table_label; - }; + +// inline and template functions +namespace internal +{ + template + inline + T TableEntry::get () const + { + // we don't quite know the data type in 'value', but + // it must be one of the ones in the type list of the + // boost::variant. so if T is not in the list, or if + // the data stored in the TableEntry is not of type + // T, then we will get an exception that we can + // catch and produce an error message + try + { + return boost::get(value); + } + catch (...) + { + Assert(false, ExcMessage ("This TableEntry object does not store a datum of type T")); + throw; + } + } + + + inline + double TableEntry::get_numeric_value () const + { + // we don't quite know the data type in 'value', but + // it must be one of the ones in the type list of the + // boost::variant. Go through this list and return + // the value if this happens to be a number + // + // first try with int + try + { + return boost::get(value); + } + catch (...) + {} + + + // ... then with unsigned int... + try + { + return boost::get(value); + } + catch (...) + {} + + // ...and finally with double precision: + try + { + return boost::get(value); + } + catch (...) + { + Assert (false, ExcMessage ("The number stored by this element of the " + "table is not a number.")) + } + + return 0; + } +} + DEAL_II_NAMESPACE_CLOSE #endif diff --git a/deal.II/source/base/table_handler.cc b/deal.II/source/base/table_handler.cc index b2e1dd5705..d9bc6c736c 100644 --- a/deal.II/source/base/table_handler.cc +++ b/deal.II/source/base/table_handler.cc @@ -2,7 +2,7 @@ // $Id$ // Version: $Name$ // -// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 by the deal.II authors +// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2011 by the deal.II authors // // This file is subject to QPL and may not be distributed // without copyright and license information. Please refer @@ -18,59 +18,14 @@ #include #include #include +#include "../../contrib/boost-1.46.1/include/boost/mpl/string.hpp" DEAL_II_NAMESPACE_OPEN - -TableEntryBase::TableEntryBase () -{} - - -TableEntryBase::~TableEntryBase () -{} - /*---------------------------------------------------------------------*/ -template -TableEntry::TableEntry(const number value) - : - val(value) -{} - - - -template -TableEntry::~TableEntry() -{} - - - -template -number TableEntry::value() const -{ - return val; -} - - - -template -void TableEntry::write_tex (std::ostream &out) const -{ - out << val; -} - - - -template -void TableEntry::write_text (std::ostream &out) const -{ - out << val; -} - - -/*---------------------------------------------------------------------*/ TableHandler::Column::Column(const std::string &tex_caption) : @@ -78,7 +33,7 @@ TableHandler::Column::Column(const std::string &tex_caption) tex_format("c"), precision(4), scientific(0), - flag(0) + flag(0) {} @@ -89,18 +44,11 @@ TableHandler::Column::Column() tex_format("c"), precision(4), scientific(0), - flag(0) + flag(0) {} -TableHandler::Column::~Column() -{ - for (unsigned int i=0; i -void TableHandler::add_value (const std::string &key, +void TableHandler::add_value (const std::string &key, const number value) { - if (!columns.count(key)) + if (columns.find(key) == columns.end()) { std::pair new_column(key, Column(key)); columns.insert(new_column); column_order.push_back(key); } - - TableEntry *entry_ptr=new TableEntry(value); - const std::map::iterator col_iter=columns.find(key); - Assert(col_iter!=columns.end(), ExcInternalError()); - - col_iter->second.entries.push_back(entry_ptr); + + const internal::TableEntry entry = { value }; + columns[key].entries.push_back (entry); } + void TableHandler::add_column_to_supercolumn (const std::string &key, const std::string &superkey) { @@ -145,12 +92,12 @@ void TableHandler::add_column_to_supercolumn (const std::string &key, column_order[j]=superkey; break; } - } - else + } + else { // remove key from column_order // for erase we need an iterator - for (std::vector::iterator order_iter=column_order.begin(); + for (std::vector::iterator order_iter=column_order.begin(); order_iter!=column_order.end(); ++order_iter) if (*order_iter==key) { @@ -172,6 +119,7 @@ void TableHandler::add_column_to_supercolumn (const std::string &key, } + void TableHandler::set_column_order (const std::vector &new_order) { for (unsigned int j=0; j &new_order) } -void TableHandler::set_tex_caption (const std::string &key, +void TableHandler::set_tex_caption (const std::string &key, const std::string &tex_caption) { Assert(columns.count(key), ExcColumnNotExistent(key)); columns[key].tex_caption=tex_caption; } + + void TableHandler::set_tex_table_caption (const std::string &table_caption) { tex_table_caption=table_caption; } + + void TableHandler::set_tex_table_label (const std::string &table_label) { tex_table_label=table_label; } + + void TableHandler::set_tex_supercaption (const std::string &superkey, const std::string &tex_supercaption) { @@ -208,6 +162,7 @@ void TableHandler::set_tex_supercaption (const std::string &superkey, } + void TableHandler::set_tex_format (const std::string &key, const std::string &tex_format) { @@ -218,6 +173,7 @@ void TableHandler::set_tex_format (const std::string &key, } + void TableHandler::set_precision (const std::string &key, const unsigned int precision) { @@ -236,8 +192,8 @@ void TableHandler::set_scientific (const std::string &key, void TableHandler::write_text(std::ostream &out) const { - AssertThrow (out, ExcIO()); - + AssertThrow (out, ExcIO()); + std::vector sel_columns; get_selected_columns(sel_columns); @@ -256,22 +212,23 @@ void TableHandler::write_text(std::ostream &out) const const std::map::const_iterator col_iter=columns.find(key); Assert(col_iter!=columns.end(), ExcInternalError()); - + const Column & column = col_iter->second; // write it into a dummy // stream, just to get its // size upon output std::ostringstream dummy_out; - + dummy_out << std::setprecision(column.precision); if (col_iter->second.scientific) dummy_out.setf (std::ios::scientific, std::ios::floatfield); else dummy_out.setf (std::ios::fixed, std::ios::floatfield); - column.entries[i]->write_text (dummy_out); - + + dummy_out << column.entries[i].value; + // get size, note that we are // not interested in the // trailing \0 @@ -290,7 +247,7 @@ void TableHandler::write_text(std::ostream &out) const for (unsigned int j=0; j::const_iterator col_iter=columns.find(key); Assert(col_iter!=columns.end(), ExcInternalError()); - + const Column &column=col_iter->second; - + out << std::setprecision(column.precision); if (col_iter->second.scientific) @@ -331,7 +288,7 @@ void TableHandler::write_text(std::ostream &out) const else out.setf(std::ios::fixed, std::ios::floatfield); out << std::setw(column_widths[j]); - column.entries[i]->write_text(out); + out << column.entries[i].value; out << " "; } out << std::endl; @@ -346,7 +303,7 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const out << "\\documentclass[10pt]{report}" << std::endl << "\\usepackage{float}" << std::endl << std::endl << std::endl << "\\begin{document}" << std::endl; - + out << "\\begin{table}[H]" << std::endl << "\\begin{center}" << std::endl << "\\begin{tabular}{|"; @@ -359,7 +316,7 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const { std::string key=column_order[j]; // avoid `supercolumns[key]' - const std::map >::const_iterator + const std::map >::const_iterator super_iter=supercolumns.find(key); if (super_iter!=supercolumns.end()) @@ -371,7 +328,7 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const const std::map::const_iterator col_iter=columns.find(super_iter->second[k]); Assert(col_iter!=columns.end(), ExcInternalError()); - + out << col_iter->second.tex_format << "|"; } } @@ -387,20 +344,20 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const out << "} \\hline" << std::endl; // write the caption line of the table - + for (unsigned int j=0; j >::const_iterator + const std::map >::const_iterator super_iter=supercolumns.find(key); if (super_iter!=supercolumns.end()) { const unsigned int n_subcolumns=super_iter->second.size(); // avoid use of `tex_supercaptions[key]' - std::map::const_iterator + std::map::const_iterator tex_super_cap_iter=tex_supercaptions.find(key); - out << std::endl << "\\multicolumn{" << n_subcolumns << "}{|c|}{" + out << std::endl << "\\multicolumn{" << n_subcolumns << "}{|c|}{" << tex_super_cap_iter->second << "}"; } else @@ -421,7 +378,7 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const for (unsigned int i=0; i::const_iterator col_iter=columns.find(key); Assert(col_iter!=columns.end(), ExcInternalError()); - + const Column &column=col_iter->second; - + out << std::setprecision(column.precision); if (col_iter->second.scientific) out.setf(std::ios::scientific, std::ios::floatfield); else out.setf(std::ios::fixed, std::ios::floatfield); - - column.entries[i]->write_tex(out); - + + out << column.entries[i].value; + if (jfirst; for (++col_iter; col_iter!=columns.end(); ++col_iter) - Assert(col_iter->second.entries.size()==n, - ExcWrongNumberOfDataEntries(col_iter->first, - col_iter->second.entries.size(), + Assert(col_iter->second.entries.size()==n, + ExcWrongNumberOfDataEntries(col_iter->first, + col_iter->second.entries.size(), first_name, n)); return n; @@ -478,11 +435,11 @@ unsigned int TableHandler::n_rows() const void TableHandler::get_selected_columns(std::vector &sel_columns) const { sel_columns.clear(); - + for (unsigned int j=0; j >::const_iterator + const std::map >::const_iterator super_iter=supercolumns.find(key); if (super_iter!=supercolumns.end()) @@ -507,13 +464,6 @@ void TableHandler::get_selected_columns(std::vector &sel_columns) c // explicit instantiations -template class TableEntry; -template class TableEntry; -template class TableEntry; -template class TableEntry; -template class TableEntry; - - template void TableHandler::add_value (const std::string &, const double); -- 2.39.5