* stores some convergence data, such as residuals of the cg-method, or some evaluated
* $L^2$-errors of discrete solutions, etc, and evaluates convergence rates or orders.
*
- * The already implemented #RateMode#s are #ConvergenceTable::standard#,
+ * The already implemented #RateMode#s are #ConvergenceTable::reduction_rate#,
* where the convergence rate is the quotient of two following rows, and
- * #ConvergenceTable::standard_order#, that evaluates the order of convergence.
+ * #ConvergenceTable::reduction_rate_log2#, that evaluates the order of convergence.
* These standard evaluations are useful for global refinement, for local refinement
* this may not be a appropriate method, as the convergence rates should be
* set in relation to the number of cells or the number of DoFs. The
- * implementations of these non-standard methods is left to the fantasy of a
- * fanatic user.
+ * implementations of these non-standard methods is left to a user.
*
* \subsection{Usage}
- * The number of cells and the number of DoFs are added to the table by
- * calling #add_run(unsigned int ncells, unsigned int ndofs)#. The
- * data is added by #add_value(...)# of the base class #TableHandler#.
- * Before the output of the table the function #evaluate_convergence_rates#
- * may be (also multiply) called.
- *
+ * The number of cells and the number of DoFs may be added to the table by
+ * calling e.g. #add_value("n cells", n_cells)#. The table
+ * data is also added by calling #add_value(...)#.
+ * Before the output of the table the functions #evaluate_convergence_rates(...)# and
+ * #evaluate_all_convergence_rates(...)# may be (also multiply) called.
+ *
+ * There are two possibilities of how to evaluate the convergence rates of multiple
+ * columns in the same #RateMode#.
+ * \begin{enumeration}
+ * \item call #evaluate_convergence_rates(data_column_key, ...)# for all wanted columns
+ * \item call #omit_column_from_convergence_rate_evaluation(data_column_key)# for all
+ * NOT wanted columns and then
+ * #evaluate_all_convergence_rates(...)# to evaluate the convergence rates of all columns
+ * that are not signed to be omitted.
+ * \end{enumeration}
+ *
*
* @author Ralf Hartmann, 1999
*/
*/
ConvergenceTable();
+ /**
+ * Rate in relation to the rows (without a
+ * reference column):
+ *
+ * #reduction_rate#: $value(row-1)/value(row)$.
+ *
+ * #reduction_rate_log2#: the order $O(h^r) of
+ * the reduction rate with the assumption
+ * row-1: h, row: h/2. Hence the order
+ * is evaluated by
+ * $\log(value(row-1)/value(row))/\log 2$.
+ *
+ * Rate in relation to a reference column:
+ *
+ * #reduction_rate#: Not implemented.
+ *
+ * #reduction_rate_log2#: Not implemented.
+ */
enum RateMode {
- none, standard, standard_order, n_cells, n_dofs
+ none,
+ reduction_rate,
+ reduction_rate_log2
};
-
+
/**
- * Adds the basic information
- * (number of cells, number of DoFs)
- * of a new run.
+ * Evaluates the convergence rates of the
+ * data column #data_column_key#
+ * due to the #RateMode# in relation to
+ * the reference column #reference_column_key#.
+ * Be sure that the value types of the
+ * table entries of the
+ * data column and the reference data column
+ * is a number, i.e. double, float,
+ * (unsigned) int, and so on.
+ *
+ * The new rate column and the data column
+ * will be merged to a supercolumn. The
+ * tex caption of the supercolumn will be
+ * (by default) the same as the one of the
+ * data column. This may be changed by using
+ * the #set_tex_supercaption (...)# function
+ * of the base class #TableHandler#.
+ *
+ * Still not implemented.
*/
- void add_run (unsigned int ncells,
- unsigned int ndofs);
+ void evaluate_convergence_rates (const string &data_column_key,
+ const string &reference_column_key,
+ const RateMode rate_mode);
+
/**
* Evaluates the convergence rates of the
- * column #key# due to a #RateMode# and
- * merges the rate column and this column
- * to a supercolumn.
+ * data column #data_column_key#
+ * due to the #RateMode#.
+ * Be sure that the value types of the
+ * table entries of the data column
+ * is a number, i.e. double, float,
+ * (unsigned) int, and so on.
+ *
+ * The new rate column and the data column
+ * will be merged to a supercolumn. The
+ * tex caption of the supercolumn will be
+ * (by default) the same as the one of the
+ * data column. This may be changed by using
+ * the #set_tex_supercaption (...)# function
+ * of the base class #TableHandler#.
*/
- void evaluate_convergence_rates (const string &key,
- const RateMode conv_rate);
+ void evaluate_convergence_rates (const string &data_column_key,
+ const RateMode rate_mode);
/**
- * Evaluate the convergence rates of
- * all (not "n cells" or "n dofs")
- * columns due to a #RateMode#.
+ * Omit this column #key#
+ * (not supercolumn!) from the
+ * evaluation of the convergence rates
+ * of `all' columns (see the following
+ * two functions).
+ *
+ * The Column::flag==1 is preserved for
+ * omitting the column from convergence
+ * rate evalution.
*/
- void evaluate_convergence_rates(const RateMode conv_rate);
+ void omit_column_from_convergence_rate_evaluation(const string &key);
- /**
- * Exception
+ /**
+ * Evaluates convergence rates
+ * due to the #rate_mode# in relation
+ * to the reference column
+ * #reference_column_key#. This
+ * function evaluates the rates of
+ * ALL columns except of the
+ * #omit_columns# and previously
+ * evaluated rate columns.
+ * This function allows to evaluate
+ * the convergence rate for almost all
+ * columns of a table without calling
+ * #evaluate_convergence_rates(data_column, ...)#
+ * for each column seperately.
+ *
+ * Example:
+ * Columns like #n cells# or
+ * #n dofs# columns may be wanted
+ * to be omitted in the evaluation
+ * of the convergence rates. Hence they
+ * should be included into #omit_columns#.
*/
- DeclException0 (ExcWrongValueType)
+ void evaluate_all_convergence_rates(const string &reference_column_key,
+ const RateMode rate_mode);
- private:
/**
- * Preset string "n cells".
+ * Evaluates convergence rates
+ * due to the #rate_mode#. This
+ * function evaluates the rates of
+ * ALL columns except of the
+ * #omit_columns# and previously
+ * evaluated rate columns.
+ * This function allows to evaluate
+ * the convergence rate for almost all
+ * columns of a table without calling
+ * #evaluate_convergence_rates(data_column, ...)#
+ * for each column seperately.
+ *
+ * Example:
+ * Columns like #n cells# or
+ * #n dofs# columns may be wanted
+ * to be omitted in the evaluation
+ * of the convergence rates. Hence they
+ * should be included into #omit_columns#.
*/
- string n_cells_string;
+ void evaluate_all_convergence_rates(const RateMode rate_mode);
- /**
- * Preset string "n dofs".
+ /**
+ * Exception
+ */
+ DeclException0 (ExcWrongValueType);
+
+ /**
+ * Exception
*/
- string n_dofs_string;
+ DeclException1 (ExcRateColumnAlreadyExists,
+ string,
+ << "Rate column <" << arg1 << "> does already exist.");
};
/**
* Change the order of columns and
* supercolumns in the table.
+ *
+ * #new_order# includes the keys and
+ * superkeys of the columns and
+ * supercolumns in the order the user like to.
+ * If a superkey is included the keys
+ * of the subcolumns need not to be additionally
+ * mentioned in this vector.
+ * The order of subcolumns within a supercolumn
+ * is not changeable and keeps the order
+ * in which
+ * the columns are added to the supercolumn.
+ *
+ * This function may also be used to break
+ * big tables with to many columns into smaller
+ * ones. Call this function with
+ * the first e.g. five columns and then #write_*#.
+ * Afterwards call this function with the
+ * next e.g. five columns and again #write_*#,
+ * and so on.
*/
void set_column_order (const vector<string> &new_order);
/**
- * Sets the output format of a column.
+ * Sets the #precision# e.g. double or float
+ * variables are written with. #precision# is
+ * the same as in calling
+ * #out << setprecision(precision)#.
*/
void set_precision (const string &key,
const unsigned int precision);
/**
* Sets the tex output format of a column.
- * e.g. #c#, #r#, #l#, or #p{3cm}#.
+ * e.g. #c#, #r#, #l#, or #p{3cm}#. The
+ * default is #c#. Also if this function
+ * is not called for a column, the default
+ * is preset to be #c#.
*/
void set_tex_format (const string &key,
- const string &format);
+ const string &format="c");
/**
* Write table as formatted text, e.g.
DeclException4 (ExcWrongNumberOfDataEntries,
string, int, string, int,
<< "Column <" << arg1 << "> has got " << arg2
- << "rows, but Column <" << arg3 << "> has got " << arg4 << ".");
+ << " rows, but Column <" << arg3 << "> has got " << arg4 << ".");
/**
* Exception
void get_selected_columns (vector<string> &sel_columns) const;
/**
- * Builtin function, that checks if
- * the number of rows is equal in every
- * row. This function is e.g. called before
+ * Builtin function, that gives the
+ * number of rows in the table and
+ * that checks if the number of rows
+ * is equal in every
+ * column. This function is e.g. called before
* writing output.
*/
- unsigned int check_n_rows() const;
+ unsigned int n_rows() const;
/**
* Stores the column and
#include <math.h>
-ConvergenceTable::ConvergenceTable():
- n_cells_string("n cells"),
- n_dofs_string("n dofs")
+ConvergenceTable::ConvergenceTable()
{}
-void ConvergenceTable::add_run (unsigned int ncells,
- unsigned int ndofs)
+void ConvergenceTable::evaluate_convergence_rates(const string &data_column_key,
+ const string &reference_column_key,
+ const RateMode rate_mode)
{
- add_value(n_cells_string, ncells);
- add_value(n_dofs_string, ndofs);
+ Assert(columns.count(data_column_key),
+ ExcColumnNotExistent(data_column_key));
+ Assert(columns.count(reference_column_key),
+ ExcColumnNotExistent(reference_column_key));
+
+ if (rate_mode==none)
+ return;
+
+ vector<TableEntryBase *> &entries=columns[data_column_key].entries;
+ string rate_key=data_column_key;
+
+ const unsigned int n=entries.size();
+
+ vector<double> values(n);
+ for (unsigned int i=0; i<n; ++i)
+ {
+ if (dynamic_cast<TableEntry<double>*>(entries[i]) != 0)
+ values[i]=dynamic_cast<TableEntry<double>*>(entries[i])->value();
+ else if (dynamic_cast<TableEntry<float>*>(entries[i]) != 0)
+ values[i]=dynamic_cast<TableEntry<float>*>(entries[i])->value();
+ else if (dynamic_cast<TableEntry<int>*>(entries[i]) != 0)
+ values[i]=dynamic_cast<TableEntry<int>*>(entries[i])->value();
+ else if (dynamic_cast<TableEntry<unsigned int>*>(entries[i]) != 0)
+ values[i]=dynamic_cast<TableEntry<unsigned int>*>(entries[i])->value();
+ else
+ Assert(false, ExcWrongValueType());
+ }
+
+ switch (rate_mode)
+ {
+ case none:
+ break;
+ case reduction_rate:
+ case reduction_rate_log2:
+ default:
+ Assert(false, ExcNotImplemented());
+ }
+
+ Assert(columns.count(rate_key), ExcInternalError());
+ columns[rate_key].flag=1;
+ set_precision(rate_key, 3);
+
+ string superkey=data_column_key;
+ if (!supercolumns.count(superkey))
+ {
+ add_column_to_supercolumn(data_column_key, superkey);
+ set_tex_supercaption(superkey, columns[data_column_key].tex_caption);
+ }
+
+ add_column_to_supercolumn(rate_key, superkey);
}
-void ConvergenceTable::evaluate_convergence_rates(const string &key,
+void ConvergenceTable::evaluate_convergence_rates(const string &data_column_key,
const RateMode rate_mode)
{
- Assert(columns.count(key), ExcColumnNotExistent(key));
+ Assert(columns.count(data_column_key), ExcColumnNotExistent(data_column_key));
- vector<TableEntryBase *> &entries=columns[key].entries;
- string rate_key=key;
+ vector<TableEntryBase *> &entries=columns[data_column_key].entries;
+ string rate_key=data_column_key+"...";
const unsigned int n=entries.size();
values[i]=dynamic_cast<TableEntry<double>*>(entries[i])->value();
else if (dynamic_cast<TableEntry<float>*>(entries[i]) != 0)
values[i]=dynamic_cast<TableEntry<float>*>(entries[i])->value();
+ else if (dynamic_cast<TableEntry<int>*>(entries[i]) != 0)
+ values[i]=dynamic_cast<TableEntry<int>*>(entries[i])->value();
+ else if (dynamic_cast<TableEntry<unsigned int>*>(entries[i]) != 0)
+ values[i]=dynamic_cast<TableEntry<unsigned int>*>(entries[i])->value();
else
Assert(false, ExcWrongValueType());
}
switch (rate_mode)
{
- case standard:
- rate_key+="s";
- // no value availble for the
+ case none:
+ break;
+ case reduction_rate:
+ rate_key+="red.rate";
+ Assert(columns.count(rate_key)==0, ExcRateColumnAlreadyExists(rate_key));
+ // no value available for the
// first row
add_value(rate_key, string("-"));
for (unsigned int i=1; i<n; ++i)
add_value(rate_key, values[i-1]/values[i]);
break;
- case standard_order:
- rate_key+="so";
+ case reduction_rate_log2:
+ rate_key+="red.rate.log2";
+ Assert(columns.count(rate_key)==0, ExcRateColumnAlreadyExists(rate_key));
// no value availble for the
// first row
add_value(rate_key, string("-"));
for (unsigned int i=1; i<n; ++i)
add_value(rate_key, log(values[i-1]/values[i])/log(2));
break;
- case n_cells:
- case n_dofs:
- case none:
- break;
default:
ExcNotImplemented();
}
Assert(columns.count(rate_key), ExcInternalError());
columns[rate_key].flag=1;
set_precision(rate_key, 3);
-
- string superkey="s"+key;
+
+ // set the superkey equal to the key
+ string superkey=data_column_key;
+ // and set the tex caption of the supercolumn
+ // to the tex caption of the data_column.
if (!supercolumns.count(superkey))
{
- add_column_to_supercolumn(key, superkey);
- set_tex_supercaption(superkey, columns[key].tex_caption);
+ add_column_to_supercolumn(data_column_key, superkey);
+ set_tex_supercaption(superkey, columns[data_column_key].tex_caption);
}
add_column_to_supercolumn(rate_key, superkey);
}
-
-void ConvergenceTable::evaluate_convergence_rates(const RateMode rate_mode)
+void ConvergenceTable::omit_column_from_convergence_rate_evaluation(const string &key)
{
- // make sure that no convergence rates
- // are evaluated for the n_cells and the
- // n_dofs column.
- Assert(columns.count(n_cells_string), ExcInternalError());
- Assert(columns.count(n_dofs_string), ExcInternalError());
-
- columns[n_cells_string].flag=1;
- columns[n_dofs_string].flag=1;
+ Assert(columns.count(key), ExcColumnNotExistent(key));
- check_n_rows();
+ const map<string, Column>::iterator col_iter=columns.find(key);
+ col_iter->second.flag=1;
+}
+
+
+void ConvergenceTable::evaluate_all_convergence_rates(const string &reference_column_key,
+ const RateMode rate_mode)
+{
+ for (map<string, Column>::const_iterator col_iter=columns.begin();
+ col_iter!=columns.end(); ++col_iter)
+ if (!col_iter->second.flag)
+ evaluate_convergence_rates(col_iter->first, reference_column_key, rate_mode);
+}
+
+
+void ConvergenceTable::evaluate_all_convergence_rates(const RateMode rate_mode)
+{
for (map<string, Column>::const_iterator col_iter=columns.begin();
col_iter!=columns.end(); ++col_iter)
if (!col_iter->second.flag)
}
out << endl;
- const unsigned int n_rows=check_n_rows();
- for (unsigned int i=0; i<n_rows; ++i)
+ const unsigned int nrows=n_rows();
+ for (unsigned int i=0; i<nrows; ++i)
{
const unsigned int n_cols=sel_columns.size();
out << "\\\\ \\hline" << endl;
// write the n rows
- const unsigned int n_rows=check_n_rows();
- for (unsigned int i=0; i<n_rows; ++i)
+ const unsigned int nrows=n_rows();
+ for (unsigned int i=0; i<nrows; ++i)
{
const unsigned int n_cols=sel_columns.size();
}
-unsigned int TableHandler::check_n_rows() const
+unsigned int TableHandler::n_rows() const
{
map<string, Column>::const_iterator col_iter=columns.begin();
unsigned int n=col_iter->second.entries.size();
const unsigned int n_subcolumns=super_iter->second.size();
for (unsigned int j=0; j<n_subcolumns; ++j)
{
- const string sub_key=super_iter->second[j];
- Assert(columns.count(sub_key), ExcInternalError());
- sel_columns.push_back(super_iter->second[j]);
+ const string subkey=super_iter->second[j];
+ Assert(columns.count(subkey), ExcInternalError());
+ sel_columns.push_back(subkey);
}
}
else
sel_columns.push_back(key);
}
}
+ cout << endl;
}