]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Updated code to use VectorTools::NormType
authorLuca Heltai <luca.heltai@sissa.it>
Tue, 30 Apr 2019 14:37:34 +0000 (16:37 +0200)
committerLuca Heltai <luca.heltai@sissa.it>
Tue, 30 Apr 2019 15:46:05 +0000 (17:46 +0200)
23 files changed:
include/deal.II/base/parsed_convergence_table.h
include/deal.II/base/parsed_convergence_table_flags.h [deleted file]
include/deal.II/numerics/vector_tools.h
source/base/parsed_convergence_table.cc
tests/base/parsed_convergence_table_01.cc
tests/base/parsed_convergence_table_01.output
tests/base/parsed_convergence_table_02.output
tests/base/parsed_convergence_table_03.cc
tests/base/parsed_convergence_table_03.output
tests/base/parsed_convergence_table_04.cc
tests/base/parsed_convergence_table_04.output
tests/base/parsed_convergence_table_05.cc
tests/base/parsed_convergence_table_05.output
tests/base/parsed_convergence_table_06.cc
tests/base/parsed_convergence_table_06.output
tests/base/parsed_convergence_table_07.cc
tests/base/parsed_convergence_table_07.output
tests/base/parsed_convergence_table_08.cc
tests/base/parsed_convergence_table_08.output
tests/base/parsed_convergence_table_09.cc
tests/base/parsed_convergence_table_09.output
tests/base/parsed_convergence_table_10.cc
tests/base/parsed_convergence_table_10.output

index 2ec1f233c1b7853295e5a0885d5209e2b6f94b71..a0c12ec1d66d347e258cd9641065a9558abaa693 100644 (file)
@@ -22,7 +22,6 @@
 #include <deal.II/base/function.h>
 #include <deal.II/base/function_parser.h>
 #include <deal.II/base/parameter_handler.h>
-#include <deal.II/base/parsed_convergence_table_flags.h>
 #include <deal.II/base/quadrature_lib.h>
 #include <deal.II/base/utilities.h>
 
@@ -64,19 +63,24 @@ DEAL_II_NAMESPACE_OPEN
  * @endcode
  *
  * The above code constructs a ParsedConvergenceTable that works for
- * scalar problems, and will produce an error table with `H1`, `L2`, and
- * `Linfty` norms of the error.
+ * scalar problems, and will produce an error table with `H1_norm`, `L2_norm`,
+ * and `Linfty_norm` norms of the error.
  *
  * Whenever a call to the methods error_from_exact() or difference() is made,
- * the instance of this class inspects its parameters, and computes all norms
+ * the instance of this class inspects its parameters, computes all norms
  * specified by the parameter given at construction time, possibly modified
- * via a parameter file.
+ * via a parameter file, computes all extra column entries specified using the
+ * method add_extra_column(), and writes one row of the convergence table.
+ *
+ * Once you have finished with the computations, a call to output_table() will
+ * generate a formatted convergence table on the provided stream, and to the
+ * file (if any) specified in the parameter file.
  *
  * With a small modification, the same code can be used to estimate the errors
  * of mixed or multi-physics problems, e.g.:
  * @code
- * using namespace ParsedConvergenceTableFlags;
- * ParsedConvergenceTable table({"u,u,p"},{{H1, L2}, {L2}});
+ * using namespace VectorTools;
+ * ParsedConvergenceTable table({"u,u,p"},{{H1_norm, L2_norm}, {L2_norm}});
  *
  * ParameterHandler prm;
  * table.add_parameters(prm);
@@ -96,16 +100,20 @@ DEAL_II_NAMESPACE_OPEN
  * components) and `L2` error in the pressure field.
  *
  * By calling the method add_parameters() passing a ParameterHandler object,
- * the following options will be defined in the given ParameterHandler object,
+ * the following options will be defined in the given ParameterHandler object
+ * (in the current level of the ParameterHandler object, i.e., whatever level
+ * you have entered with the ParamterHandler::enter_subsection() method),
  * and can be modified at run time through a parameter file:
  * @code
  * set Enable computation of the errors = true
  * set Enable output to streams         = true
  * set Error file name                  =
  * set Error precision                  = 3
+ * set Exponent for p-norms             = 2
  * set Extra columns                    = dofs, cells
- * set List of error norms to compute   = Linfty, L2, H1
+ * set List of error norms to compute   = Linfty_norm, L2_norm, H1_norm
  * set Rate key                         = dofs
+ * set Rate mode                        = reduction_rate_log2
  * @endcode
  *
  * When using this class, please cite
@@ -141,13 +149,14 @@ public:
    *
    * For example, the following constructor
    * @code
-   * using namespace ParsedConvergenceTableFlags;
-   * ParsedConvergenceTable table({"u", "v", "v"}, {{Linfty}, {L2, H1}});
+   * using namespace VectorTools;
+   * ParsedConvergenceTable table({"u", "v", "v"},
+   *                              {{Linfty_norm}, {L2_norm, H1_norm}});
    * @endcode
    *
-   * Will produce (if the parameter file is left untouched) the following table:
+   * Would produce (if the parameter file is left untouched) a table similar to
    * @code
-   * cells dofs    u_Linfty         v_L2           v_H1
+   * cells dofs u_Linfty_norm    v_L2_norm      v_H1_norm
    * 4     9    1.183e-01 -    5.156e-02 -    2.615e-01 -
    * 16    25   3.291e-02 2.50 1.333e-02 2.65 1.272e-01 1.41
    * 64    81   8.449e-03 2.31 3.360e-03 2.34 6.313e-02 1.19
@@ -155,7 +164,7 @@ public:
    * 1024  1089 5.325e-04 2.09 2.106e-04 2.09 1.574e-02 1.05
    * @endcode
    *
-   * Se the documentation of NormType for a list of
+   * Se the documentation of VectorTools::NormType for a list of
    * available norms you can compute using this class, and see the other
    * constructor for a documentation of all the parameters you can change.
    *
@@ -164,11 +173,9 @@ public:
    * unique component name
    */
   ParsedConvergenceTable(
-    const std::vector<std::string> &component_names = {"u"},
-    const std::vector<std::set<ParsedConvergenceTableFlags::NormType>>
-      &list_of_error_norms = {{ParsedConvergenceTableFlags::H1,
-                               ParsedConvergenceTableFlags::L2,
-                               ParsedConvergenceTableFlags::Linfty}});
+    const std::vector<std::string> &                    component_names = {"u"},
+    const std::vector<std::set<VectorTools::NormType>> &list_of_error_norms = {
+      {VectorTools::H1_norm, VectorTools::L2_norm, VectorTools::Linfty_norm}});
 
   /**
    * Full constructor for ParsedConvergenceTable.
@@ -177,19 +184,27 @@ public:
    * names are interpreted as components of a vector valued field;
    * @param list_of_error_norms Specify what error norms to compute for each
    * unique component name;
-   * @param extra_columns Extra columns to add;
+   * @param exponent The exponent to use in p-norms;
+   * @param extra_columns Extra columns to add. These may be "cells" or "dofs";
    * @param rate_key Specify the extra column by which we will compute the
-   * error rates;
+   * error rates. This key can either be one of "cells" or "dofs", or, if you
+   * add extra columns to the table via the method add_extra_column(), it may
+   * be one of the extra columns you added;
+   * @param rate_mode Specify the rate mode to use when computing error rates.
+   * This maybe either "reduction_rate", "reduction_rate_log2", or "none". See
+   * the documentation of ConvergenceTable::RateMode for an explanation of how
+   * each of this mode behaves;
    * @param error_file_name Name of error output file (with extension txt,
    * gpl, tex, or org). If different from the empty string, than
    * output_table() also writes in this file in the format deduced from its
    * extension;
    * @param precision How many digits to use when writing the error;
-   * @param compute_error If set to `false`, then no error computation is
-   * performed, and no output is produced;
-   * @param output_error If set to `false`, then the call to output_table()
-   * will produce only an output file (if @p error_file_name is not empty),
-   * but no output will be written on the given stream.
+   * @param compute_error Control wether the filling of the table is enabled
+   * or not. This flag may be used to disable at run time any error computation;
+   * @param output_error Control the behaviour of the output_table() method. Set
+   * this to true if you want output_table() to write the table to its input
+   * argument. This flag may be used to disable at run time any explicit output
+   * to stream.
    *
    * The parameters you specify with this constructor can be written to a
    * ParameterHandler object by calling the add_parameters() method. Once you
@@ -214,10 +229,12 @@ public:
    * # Number of digits to use when printing the error.
    * set Error precision                  = 3
    *
-   * # Extra columns to add to the table. Available options are dofs, cells, and
-   * # dt.
+   * # Extra columns to add to the table. Available options are dofs and cells
    * set Extra columns                    = dofs, cells
    *
+   * # The exponent to use when computing p-norms.
+   * set Exponent for p-norms             = 2
+   *
    * # Each component is separated by a semicolon, and each norm by a comma.
    * # Implemented norms are Linfty, L2, W1infty, H1, and custom. If you want to
    * # skip a component, use none.
@@ -226,18 +243,23 @@ public:
    * # Key to use when computing convergence rates. If this is set to a
    * # column that is not present, or to none, then no error rates are computed.
    * set Rate key                         = dofs
+   *
+   * # What type of error rate to compute. Available options are
+   * # reduction_rate_log2, reduction_rate, and none.
+   * set Rate mode                        = reduction_rate_log2
    * @endcode
    */
   ParsedConvergenceTable(
-    const std::vector<std::string> &component_names,
-    const std::vector<std::set<ParsedConvergenceTableFlags::NormType>>
-      &list_of_error_norms,
-    const std::set<ParsedConvergenceTableFlags::ExtraColumns> &extra_columns,
-    const ParsedConvergenceTableFlags::ExtraColumns &          rate_key,
-    const std::string &                                        error_file_name,
-    const unsigned int &                                       precision,
-    const bool &                                               compute_error,
-    const bool &                                               output_error);
+    const std::vector<std::string> &                    component_names,
+    const std::vector<std::set<VectorTools::NormType>> &list_of_error_norms,
+    const double &                                      exponent,
+    const std::set<std::string> &                       extra_columns,
+    const std::string &                                 rate_key,
+    const std::string &                                 rate_mode,
+    const std::string &                                 error_file_name,
+    const unsigned int &                                precision,
+    const bool &                                        compute_error,
+    const bool &                                        output_error);
 
   /**
    * Attach all the parameters in this class to entries of the parameter
@@ -251,111 +273,100 @@ public:
    * Add a row to the error table, containing the error between @p solution and
    * the @p exact function, in the norm(s) specified in the parameter file.
    *
-   * If you specify a @p weight expression during this call, then this is used
-   * to compute weighted errors. If the weight is different from "1.0", then
-   * you have to make sure that muparser is installed and enabled, otherwise an
-   * exception will be thrown.
+   * If you specify a @p weight function during this call, then this is used
+   * to compute weighted errors. The weight function can be either a scalar
+   * function (which will be used for all components), or a vector function.
+   * When it is a vector function, an assertion is triggered if the number of
+   * components does not coincide with the number of components of the
+   * underlying finite element space.
    */
   template <typename DoFHandlerType, typename VectorType>
   void
-  error_from_exact(const DoFHandlerType &                           vspace,
-                   const VectorType &                               solution,
-                   const Function<DoFHandlerType::space_dimension> &exact,
-                   double                                           dt = 0.,
-                   const std::string &weight                           = "1.0");
+  error_from_exact(
+    const DoFHandlerType &                           vspace,
+    const VectorType &                               solution,
+    const Function<DoFHandlerType::space_dimension> &exact,
+    const Function<DoFHandlerType::space_dimension> *weight = nullptr);
 
   /**
    * Same as above, with a different mapping.
    */
   template <typename DoFHandlerType, typename VectorType>
   void
-  error_from_exact(const Mapping<DoFHandlerType::dimension,
-                                 DoFHandlerType::space_dimension> & mapping,
-                   const DoFHandlerType &                           vspace,
-                   const VectorType &                               solution,
-                   const Function<DoFHandlerType::space_dimension> &exact,
-                   double                                           dt = 0.,
-                   const std::string &weight                           = "1.0");
-
+  error_from_exact(
+    const Mapping<DoFHandlerType::dimension, DoFHandlerType::space_dimension>
+      &                                              mapping,
+    const DoFHandlerType &                           vspace,
+    const VectorType &                               solution,
+    const Function<DoFHandlerType::space_dimension> &exact,
+    const Function<DoFHandlerType::space_dimension> *weight = nullptr);
 
   /**
-   * Call the given custom function to compute a custom error for any component
-   * for which you specify the ParsedConvergenceTableFlags::custom norm. This function
-   * may be called several times to add different columns with different names,
-   * provided you use an appropriate function every time, and
-   * that you also update @p column_name every time.
+   * Add an additional column (with name @p name) to the table, by invoking
+   * the function @p custom_function, when calling error_from_exact() or
+   * difference().
    *
-   * Should you wish to do so, then make sure the parameter
-   * @p add_table_extras is set to `false` for each call, except one, so
-   * that you only add extra column information once.
+   * You can call this method as many times as you want. If @p column_name was
+   * already used in a previous call, then calling this method with the same
+   * name will overwrite whatever function you had previously specified. If
+   * you use a lambda function for this call, make sure that the variables used
+   * internally in the lambda function remain valid until the call to
+   * error_from_exact() or difference().
    *
-   * An example usage of this class with a custom error function is the
-   * following:
+   * This method may be used, for example, to compute the error w.r.t. to
+   * time step increments in time, for example:
    * @code
-   * using namespace ParsedConvergenceTableFlags;
-   * ParsedConvergenceTable table({"u"}, {{"custom"}});
+   * using namespace VectorTools;
+   * ParsedConvergenceTable table({"u"}, {{L2_norm}});
+   *
+   * double dt = .5;
+   * auto dt_function = [&]() {
+   *        return dt;
+   * };
+   *
+   * table.add_extra_column("dt", dt_function,  true);
    *
    * for (unsigned int i = 0; i < n_cycles; ++i)
    *   {
-   *     // ... refine and distribute dofs
-   *     auto cycle_function = [&](const unsigned int component) {
-   *        return i;
-   *     };
-   *     table.custom_error(cycle_function, dof_handler, "cycle", true);
+   *     // ... compute solution at the current dt
+   *
+   *     table.error_from_exact(dof_handler, solution, exact_solution);
+   *     dt /= 2.0;
    *   }
    * table.output_table(std::cout);
    * @endcode
    *
-   * Will produce (if the parameter file is left untouched) the following table:
-   * @code
-   * cells dofs  cycle
-   * 4     9     0
-   * 16    25    1
-   * 64    81    2
-   * 256   289   3
-   * 1024  1089  4
-   * @endcode
+   * will produce a table similar to
    *
-   * Should you wish to add another column, then the above code should be
-   * replaced by:
    * @code
-   * using namespace ParsedConvergenceTableFlags;
-   * ParsedConvergenceTable table({"u"}, {"custom"});
-   *
-   * for (unsigned int i = 0; i < n_cycles; ++i)
-   *   {
-   *     // ... refine and distribute dofs
-   *     auto cycle_function = [&](const unsigned int) {
-   *        return i;
-   *     };
-   *     auto cycle_square_function = [&](const unsigned int) {
-   *        return i*i;
-   *     };
-   *     table.custom_error(cycle_function, dof_handler, "cycle", false);
-   *     table.custom_error(cycle_square_function, dof_handler,
-   *                        "cycle_square", true);
-   *   }
-   * table.output_table(std::cout);
+   *    dt        u_L2_norm
+   * 5.000e-1    5.156e-02 -
+   * 2.500e-2    1.333e-02 2.65
+   * 1.250e-2    3.360e-03 2.34
+   * 6.250e-3    8.418e-04 2.18
    * @endcode
    *
-   * This will produce the table:
+   * provided that you use the following parameter file (only non default
+   * entries are shown here):
+   *
    * @code
-   * cells dofs  cycle cycle_square
-   * 4     9     0     0
-   * 16    25    1     1
-   * 64    81    2     4
-   * 256   289   3     9
-   * 1024  1089  4     16
+   * set Extra columns =
+   * set List of error norms to compute   = L2_norm
+   * set Rate key                         = dt
    * @endcode
+   *
+   *
+   * @param name Name of the column to add.
+   * @param custom_function Function that will be called to fill the given
+   * entry. You need to make sure that the scope of this function is valid
+   * up to the
+   * @param exclude_from_rates If set to true, then no error rates will be
+   * computed for this column.
    */
-  template <typename DoFHandlerType>
   void
-  custom_error(const std::function<double(const unsigned int component)>
-                 &                   custom_error_function,
-               const DoFHandlerType &dh,
-               const std::string &   column_name      = "custom",
-               const bool            add_table_extras = false,
-               const double          dt               = 0.);
+  add_extra_column(const std::string &            column_name,
+                   const std::function<double()> &custom_function,
+                   const bool &                   exclude_from_rates = false);
 
   /**
    * Difference between two solutions in the same vector space.
@@ -365,7 +376,7 @@ public:
   difference(const DoFHandlerType &,
              const VectorType &,
              const VectorType &,
-             double dt = 0.);
+             const Function<DoFHandlerType::space_dimension> *weight = nullptr);
 
   /**
    * Same as above, with a non default mapping.
@@ -377,7 +388,7 @@ public:
              const DoFHandlerType &,
              const VectorType &,
              const VectorType &,
-             double dt = 0.);
+             const Function<DoFHandlerType::space_dimension> *weight = nullptr);
 
   /**
    * Write the error table to the @p out stream, and (possibly) to the file
@@ -402,26 +413,41 @@ private:
    */
   const std::vector<ComponentMask> unique_component_masks;
 
+  /**
+   * Additional methods to call when adding rows to the table.
+   */
+  std::map<std::string, std::pair<std::function<double()>, bool>>
+    extra_column_functions;
+
   /**
    * Type of error to compute per components.
    */
-  std::vector<std::set<ParsedConvergenceTableFlags::NormType>>
-    norms_per_unique_component;
+  std::vector<std::set<VectorTools::NormType>> norms_per_unique_component;
+
+  /**
+   * Exponent to use in the p-norm types.
+   */
+  double exponent;
 
   /**
    * The actual table
    */
   ConvergenceTable table;
-  
+
   /**
    * Extra columns to add to the table.
    */
-  std::set<ParsedConvergenceTableFlags::ExtraColumns> extra_columns;
+  std::set<std::string> extra_columns;
+
+  /**
+   * The name of column with respect to which we compute convergence rates.
+   */
+  std::string rate_key;
 
   /**
-   * Whether or not to calculate the rates according to the given keys.
+   * Reduction rate mode. See ConvergenceTable::RateMode for a documentation.
    */
-  ParsedConvergenceTableFlags::ExtraColumns rate_key;
+  std::string rate_mode;
 
   /**
    * The precision used to output the table.
@@ -453,10 +479,11 @@ private:
 // ============================================================
 template <typename DoFHandlerType, typename VectorType>
 void
-ParsedConvergenceTable::difference(const DoFHandlerType &dh,
-                                   const VectorType &    solution1,
-                                   const VectorType &    solution2,
-                                   double                dt)
+ParsedConvergenceTable::difference(
+  const DoFHandlerType &                           dh,
+  const VectorType &                               solution1,
+  const VectorType &                               solution2,
+  const Function<DoFHandlerType::space_dimension> *weight)
 {
   AssertThrow(solution1.size() == solution2.size(),
               ExcDimensionMismatch(solution1.size(), solution2.size()));
@@ -466,7 +493,7 @@ ParsedConvergenceTable::difference(const DoFHandlerType &dh,
                    solution,
                    ConstantFunction<DoFHandlerType::space_dimension>(
                      0, component_names.size()),
-                   dt);
+                   weight);
 }
 
 
@@ -475,11 +502,11 @@ template <typename DoFHandlerType, typename VectorType>
 void
 ParsedConvergenceTable::difference(
   const Mapping<DoFHandlerType::dimension, DoFHandlerType::space_dimension>
-    &                   mapping,
-  const DoFHandlerType &dh,
-  const VectorType &    solution1,
-  const VectorType &    solution2,
-  double                dt)
+    &                                              mapping,
+  const DoFHandlerType &                           dh,
+  const VectorType &                               solution1,
+  const VectorType &                               solution2,
+  const Function<DoFHandlerType::space_dimension> *weight)
 {
   AssertThrow(solution1.size() == solution2.size(),
               ExcDimensionMismatch(solution1.size(), solution2.size()));
@@ -490,7 +517,7 @@ ParsedConvergenceTable::difference(
                    solution,
                    ConstantFunction<DoFHandlerType::space_dimension>(
                      0, component_names.size()),
-                   dt);
+                   weight);
 }
 
 
@@ -501,15 +528,13 @@ ParsedConvergenceTable::error_from_exact(
   const DoFHandlerType &                           dh,
   const VectorType &                               solution,
   const Function<DoFHandlerType::space_dimension> &exact,
-  double                                           dt,
-  const std::string &                              weight)
+  const Function<DoFHandlerType::space_dimension> *weight)
 {
   error_from_exact(StaticMappingQ1<DoFHandlerType::dimension,
                                    DoFHandlerType::space_dimension>::mapping,
                    dh,
                    solution,
                    exact,
-                   dt,
                    weight);
 }
 
@@ -523,80 +548,80 @@ ParsedConvergenceTable::error_from_exact(
   const DoFHandlerType &                           dh,
   const VectorType &                               solution,
   const Function<DoFHandlerType::space_dimension> &exact,
-  double                                           dt,
-  const std::string &                              weight)
+  const Function<DoFHandlerType::space_dimension> *weight)
 {
-  const int dim      = DoFHandlerType::dimension;
-  const int spacedim = DoFHandlerType::space_dimension;
+  const int  dim          = DoFHandlerType::dimension;
+  const int  spacedim     = DoFHandlerType::space_dimension;
+  const auto n_components = component_names.size();
+
   if (compute_error)
     {
-      AssertDimension(exact.n_components, component_names.size());
+      AssertDimension(exact.n_components, n_components);
+      AssertDimension(dh.get_fe().n_components(), n_components);
 
       const unsigned int n_active_cells =
         dh.get_triangulation().n_global_active_cells();
       const unsigned int n_dofs = dh.n_dofs();
 
       for (const auto &col : extra_columns)
-        if (col == ParsedConvergenceTableFlags::cells)
+        if (col == "cells")
           {
             table.add_value("cells", n_active_cells);
             table.set_tex_caption("cells", "\\# cells");
             table.set_tex_format("cells", "r");
           }
-        else if (col == ParsedConvergenceTableFlags::dofs)
+        else if (col == "dofs")
           {
             table.add_value("dofs", n_dofs);
             table.set_tex_caption("dofs", "\\# dofs");
             table.set_tex_format("dofs", "r");
           }
-        else if (col == ParsedConvergenceTableFlags::dt)
-          {
-            table.add_value("dt", dt);
-            table.set_tex_caption("dt", "\\Delta t");
-            table.set_tex_format("dt", "r");
-          }
 
+      // A vector of zero std::functions with n_components components
+      const std::vector<std::function<double(const Point<spacedim> &)>>
+        zero_components(n_components,
+                        [](const Point<spacedim> &) { return 0.0; });
 
-      std::map<ParsedConvergenceTableFlags::NormType, unsigned int>
-        norm_to_index;
-      norm_to_index[ParsedConvergenceTableFlags::L2]      = 0;
-      norm_to_index[ParsedConvergenceTableFlags::H1]      = 1;
-      norm_to_index[ParsedConvergenceTableFlags::Linfty]  = 2;
-      norm_to_index[ParsedConvergenceTableFlags::W1infty] = 3;
-      norm_to_index[ParsedConvergenceTableFlags::custom]  = 4;
+      // The default weight function, with n_components components
+      std::vector<std::function<double(const Point<spacedim> &)>>
+        weight_components(n_components,
+                          [](const Point<spacedim> &) { return 1.0; });
 
-      const auto n_components = component_names.size();
-      for (unsigned int i = 0; i < unique_component_names.size(); ++i)
+      if (weight != nullptr)
         {
-          std::vector<double> error(5, 0.0);
-          const auto &        norms = norms_per_unique_component[i];
-          const auto &        mask  = unique_component_masks[i];
-
-#  ifndef DEAL_II_WITH_MUPARSER
-          Assert(weight == "1.0",
-                 ExcMessage("If you want to use a weight which is "
-                            "different from 1.0, you have to "
-                            "install deal.II with muparser enabled."));
-          ComponentSelectFunction<spacedim> select_component(
-            {mask.first_selected_component(),
-             mask.first_selected_component() + mask.n_selected_components()},
-            n_components);
-#  else
-          std::string comp_sel;
-          {
-            // Select all required components
-            std::vector<std::string> expr(n_components, "0");
+          if (weight->n_components == 1)
+            {
+              for (auto &f : weight_components)
+                f = [&](const Point<spacedim> &p) { return weight->value(p); };
+            }
+          else
+            {
+              AssertDimension(weight->n_components, n_components);
+              for (unsigned int i = 0; i < n_components; ++i)
+                weight_components[i] = [&](const Point<spacedim> &p) {
+                  return weight->value(p, i);
+                };
+            }
+        }
 
-            for (unsigned int i = 0; i < n_components; ++i)
-              if (mask[i] == true)
-                expr[i] = weight;
+      for (unsigned int i = 0; i < norms_per_unique_component.size(); ++i)
+        {
+          std::map<VectorTools::NormType, double> errors;
 
-            comp_sel = expr[0];
-            for (unsigned int i = 1; i < expr.size(); ++i)
-              comp_sel += "; " + expr[i];
-          }
-          FunctionParser<spacedim> select_component(comp_sel);
-#  endif
+          const auto &norms = norms_per_unique_component[i];
+          const auto &mask  = unique_component_masks[i];
+
+          // Simple case first
+          if (norms.empty())
+            continue;
+
+          auto components_expr = zero_components;
+          for (unsigned int i = 0; i < n_components; ++i)
+            if (mask[i] == true)
+              components_expr[i] = weight_components[i];
+
+          FunctionFromFunctionObjects<spacedim> select_component(
+            components_expr);
 
           Vector<float> difference_per_cell(
             dh.get_triangulation().n_global_active_cells());
@@ -605,164 +630,46 @@ ParsedConvergenceTable::error_from_exact(
 
           for (const auto &norm : norms)
             {
-              if (norm == ParsedConvergenceTableFlags::L2)
-                {
-                  VectorTools::integrate_difference(mapping,
-                                                    dh,
-                                                    solution,
-                                                    exact,
-                                                    difference_per_cell,
-                                                    q_gauss,
-                                                    VectorTools::L2_norm,
-                                                    &select_component);
-                }
-
-              error[norm_to_index[ParsedConvergenceTableFlags::L2]] =
-                VectorTools::compute_global_error(dh.get_triangulation(),
-                                                  difference_per_cell,
-                                                  VectorTools::L2_norm);
-              difference_per_cell = 0;
-
-              if (norm == ParsedConvergenceTableFlags::H1)
-                {
-                  VectorTools::integrate_difference(mapping,
-                                                    dh,
-                                                    solution,
-                                                    exact,
-                                                    difference_per_cell,
-                                                    q_gauss,
-                                                    VectorTools::H1_norm,
-                                                    &select_component);
-                }
-              error[norm_to_index[ParsedConvergenceTableFlags::H1]] =
-                VectorTools::compute_global_error(dh.get_triangulation(),
-                                                  difference_per_cell,
-                                                  VectorTools::H1_norm);
-              difference_per_cell = 0;
-
-              if (norm == ParsedConvergenceTableFlags::W1infty)
-                {
-                  VectorTools::integrate_difference(mapping,
-                                                    dh,
-                                                    solution,
-                                                    exact,
-                                                    difference_per_cell,
-                                                    q_gauss,
-                                                    VectorTools::W1infty_norm,
-                                                    &select_component);
-                }
-
-              error[norm_to_index[ParsedConvergenceTableFlags::W1infty]] =
-                VectorTools::compute_global_error(
-                  dh.get_triangulation(),
-                  difference_per_cell,
-                  VectorTools::W1infty_seminorm);
-              difference_per_cell = 0;
-
-              if (norm == ParsedConvergenceTableFlags::Linfty)
-                {
-                  VectorTools::integrate_difference(mapping,
-                                                    dh,
-                                                    solution,
-                                                    exact,
-                                                    difference_per_cell,
-                                                    q_gauss,
-                                                    VectorTools::Linfty_norm,
-                                                    &select_component);
-                }
-
-              error[norm_to_index[ParsedConvergenceTableFlags::Linfty]] =
-                VectorTools::compute_global_error(dh.get_triangulation(),
-                                                  difference_per_cell,
-                                                  VectorTools::Linfty_norm);
               difference_per_cell = 0;
-
-              // Now add what we just computed.
-              if (norm != ParsedConvergenceTableFlags::none)
-                {
-                  std::string name = unique_component_names[i] + "_" +
-                                     Patterns::Tools::to_string(norm);
-                  std::string latex_name =
-                    "$\\| " + unique_component_names[i] + " - " +
-                    unique_component_names[i] + "_h \\|_{" +
-                    Patterns::Tools::to_string(norm) + "}$";
-
-                  table.add_value(name, error[norm_to_index[norm]]);
-                  table.set_precision(name, precision);
-                  table.set_scientific(name, true);
-                  table.set_tex_caption(name, latex_name);
-                }
+              VectorTools::integrate_difference(mapping,
+                                                dh,
+                                                solution,
+                                                exact,
+                                                difference_per_cell,
+                                                q_gauss,
+                                                norm,
+                                                &select_component,
+                                                exponent);
+
+              errors[norm] = VectorTools::compute_global_error(
+                dh.get_triangulation(), difference_per_cell, norm, exponent);
+
+              std::string name = unique_component_names[i] + "_" +
+                                 Patterns::Tools::to_string(norm);
+              std::string latex_name = "$\\| " + unique_component_names[i] +
+                                       " - " + unique_component_names[i] +
+                                       "_h \\|_{" +
+                                       Patterns::Tools::to_string(norm) + "}$";
+
+              table.add_value(name, errors[norm]);
+              table.set_precision(name, precision);
+              table.set_scientific(name, true);
+              table.set_tex_caption(name, latex_name);
             }
         }
-    }
-}
 
-
-template <typename DoFHandlerType>
-void
-ParsedConvergenceTable::custom_error(
-  const std::function<double(const unsigned int component)>
-    &                   custom_error_function,
-  const DoFHandlerType &dh,
-  const std::string &   column_name,
-  const bool            add_table_extras,
-  const double          dt)
-{
-  if (compute_error)
-    {
-      const unsigned int  n_components = norms_per_unique_component.size();
-      const unsigned int  n_active_cells =
-        dh.get_triangulation().n_global_active_cells();
-      const unsigned int n_dofs = dh.n_dofs();
-      if (add_table_extras)
-        {
-          for (const auto &col : extra_columns)
-            {
-              if (col == ParsedConvergenceTableFlags::cells)
-                {
-                  table.add_value("cells", n_active_cells);
-                  table.set_tex_caption("cells", "\\# cells");
-                  table.set_tex_format("cells", "r");
-                }
-              if (col == ParsedConvergenceTableFlags::dofs)
-                {
-                  table.add_value("dofs", n_dofs);
-                  table.set_tex_caption("dofs", "\\# dofs");
-                  table.set_tex_format("dofs", "r");
-                }
-              if (col == ParsedConvergenceTableFlags::dt)
-                {
-                  table.add_value("dt", dt);
-                  table.set_tex_caption("dt", "\\Delta t");
-                  table.set_tex_format("dt", "r");
-                }
-            }
-        }
-
-      for (unsigned int j = 0; j < n_components; ++j)
+      for (const auto &extra_col : extra_column_functions)
         {
-          const auto &norms = norms_per_unique_component[j];
+          const double custom_error = extra_col.second.first();
 
-          for (const auto &norm : norms)
-            if (norm == ParsedConvergenceTableFlags::custom)
-              {
-                const double custom_error = custom_error_function(j);
-
-                std::string name =
-                  unique_component_names[j] + "_" + column_name;
-                std::string latex_name = "$\\| " + unique_component_names[j] +
-                                         " - " + unique_component_names[j] +
-                                         "_h \\|_{\\text{" + column_name +
-                                         "} $";
-
-                table.add_value(name, custom_error);
-                table.set_precision(name, precision);
-                table.set_scientific(name, true);
-                table.set_tex_caption(name, latex_name);
-              }
+          std::string name = extra_col.first;
+          table.add_value(name, custom_error);
+          table.set_precision(name, precision);
+          table.set_scientific(name, true);
         }
     }
 }
+
 #endif
 
 DEAL_II_NAMESPACE_CLOSE
diff --git a/include/deal.II/base/parsed_convergence_table_flags.h b/include/deal.II/base/parsed_convergence_table_flags.h
deleted file mode 100644 (file)
index 8efd967..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-// ---------------------------------------------------------------------
-//
-// Copyright (C) 2019 by the deal.II authors
-//
-// This file is part of the deal.II library.
-//
-// The deal.II library is free software; you can use it, redistribute
-// it, and/or modify it under the terms of the GNU Lesser General
-// Public License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// The full text of the license can be found in the file LICENSE.md at
-// the top level directory of deal.II.
-//
-// -------------------------------------------------------------------
-
-#ifndef dealii_base_parsed_convergence_table_flags_h
-#define dealii_base_parsed_convergence_table_flags_h
-
-#include <deal.II/base/config.h>
-
-#include <deal.II/base/patterns.h>
-
-DEAL_II_NAMESPACE_OPEN
-
-namespace ParsedConvergenceTableFlags
-{
-  /**
-   * Implemented Error norms.
-   */
-  enum NormType
-  {
-    none    = 0x00,
-    Linfty  = 0x01,
-    L2      = 0x02,
-    W1infty = 0x04,
-    H1      = 0x08,
-    custom  = 0x10,
-  };
-
-  /**
-   * The ExtraColumns enum.
-   */
-  enum ExtraColumns
-  {
-    no_columns = 0x0,
-    dofs       = 0x1,
-    cells      = 0x2,
-    dt         = 0x4
-  };
-} // namespace ParsedConvergenceTableFlags
-
-namespace Patterns
-{
-  namespace Tools
-  {
-    template <>
-    struct Convert<ParsedConvergenceTableFlags::NormType>
-    {
-      /**
-       * Return the Correct pattern for NormType.
-       */
-      static std::unique_ptr<Patterns::PatternBase>
-      to_pattern()
-      {
-        return std_cxx14::make_unique<Patterns::Selection>(
-          "none|Linfty|L2|W1infty|H1|custom");
-      }
-
-
-
-      /**
-       * Convert a NormType to a string.
-       */
-      static std::string
-      to_string(const ParsedConvergenceTableFlags::NormType & s,
-                const std::unique_ptr<Patterns::PatternBase> &p =
-                  Convert<ParsedConvergenceTableFlags::NormType>::to_pattern())
-      {
-        (void)p;
-        if (s == ParsedConvergenceTableFlags::Linfty)
-          return "Linfty";
-        else if (s == ParsedConvergenceTableFlags::L2)
-          return "L2";
-        else if (s == ParsedConvergenceTableFlags::W1infty)
-          return "W1infty";
-        else if (s == ParsedConvergenceTableFlags::H1)
-          return "H1";
-        else if (s == ParsedConvergenceTableFlags::custom)
-          return "custom";
-        else if (s == ParsedConvergenceTableFlags::none)
-          return "none";
-        else
-          {
-            AssertThrow(false, ExcMessage("Didn't recognize a norm type."));
-            return "";
-          }
-      }
-
-
-
-      /**
-       * Convert a string to a NormType.
-       */
-      static ParsedConvergenceTableFlags::NormType
-      to_value(const std::string &                           norm_string,
-               const std::unique_ptr<Patterns::PatternBase> &p =
-                 Convert<ParsedConvergenceTableFlags::NormType>::to_pattern())
-      {
-        (void)p;
-        ParsedConvergenceTableFlags::NormType norm =
-          ParsedConvergenceTableFlags::none;
-
-        if (norm_string == "Linfty")
-          {
-            norm = ParsedConvergenceTableFlags::Linfty;
-          }
-        else if (norm_string == "L2")
-          {
-            norm = ParsedConvergenceTableFlags::L2;
-          }
-        else if (norm_string == "W1infty")
-          {
-            norm = ParsedConvergenceTableFlags::W1infty;
-          }
-        else if (norm_string == "H1")
-          {
-            norm = ParsedConvergenceTableFlags::H1;
-          }
-        else if (norm_string == "custom")
-          {
-            norm = ParsedConvergenceTableFlags::custom;
-          }
-        else if (norm_string == "none")
-          {
-            norm = ParsedConvergenceTableFlags::none;
-          }
-        else
-          {
-            AssertThrow(false, ExcMessage("The norm type <" + norm_string + "> is not recognized."));
-          }
-
-        return norm;
-      }
-    };
-
-
-
-    template <>
-    struct Convert<ParsedConvergenceTableFlags::ExtraColumns>
-    {
-      /**
-       * Return the Correct pattern for ExtraColumns.
-       */
-      static std::unique_ptr<Patterns::PatternBase>
-      to_pattern()
-      {
-        return std_cxx14::make_unique<Patterns::Selection>("none|cells|dofs|dt");
-      }
-
-
-
-      /**
-       * Convert an ExtraColumn object to a string.
-       */
-      static std::string
-      to_string(
-        const ParsedConvergenceTableFlags::ExtraColumns &s,
-        const std::unique_ptr<Patterns::PatternBase> &   p =
-          Convert<ParsedConvergenceTableFlags::ExtraColumns>::to_pattern())
-      {
-        (void)p;
-        if (s == ParsedConvergenceTableFlags::cells)
-          return "cells";
-        else if (s == ParsedConvergenceTableFlags::dofs)
-          return "dofs";
-        else if (s == ParsedConvergenceTableFlags::dt)
-          return "dt";
-        else if (s == ParsedConvergenceTableFlags::no_columns)
-          return "none";
-        else
-          {
-            AssertThrow(false, ExcMessage("Didn't recognize a column type."));
-            return "";
-          }
-      }
-
-
-
-      /**
-       * Convert a string to an ExtraColumn object.
-       */
-      static ParsedConvergenceTableFlags::ExtraColumns
-      to_value(
-        const std::string &                           column_string,
-        const std::unique_ptr<Patterns::PatternBase> &p =
-          Convert<ParsedConvergenceTableFlags::ExtraColumns>::to_pattern())
-      {
-        (void)p;
-        ParsedConvergenceTableFlags::ExtraColumns column =
-          ParsedConvergenceTableFlags::no_columns;
-
-        if (column_string == "cells")
-          {
-            column = ParsedConvergenceTableFlags::cells;
-          }
-        else if (column_string == "dofs")
-          {
-            column = ParsedConvergenceTableFlags::dofs;
-          }
-        else if (column_string == "dt")
-          {
-            column = ParsedConvergenceTableFlags::dt;
-          }
-        else if (column_string == "none")
-          {
-            column = ParsedConvergenceTableFlags::no_columns;
-          }
-        else
-          {
-            AssertThrow(false,
-                        ExcMessage("The column type <" + column_string + "> is not recognized."));
-          }
-
-        return column;
-      }
-    };
-  } // namespace Tools
-} // namespace Patterns
-
-DEAL_II_NAMESPACE_CLOSE
-
-#endif
index 37b43f49ed51c9725fe93553c47235029254a5e4..139ca99ce0fec3606f1bd29495907c1e3a5754dd 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <deal.II/base/exceptions.h>
 #include <deal.II/base/function.h>
+#include <deal.II/base/patterns.h>
 #include <deal.II/base/point.h>
 #include <deal.II/base/quadrature_lib.h>
 
@@ -3308,6 +3309,119 @@ namespace VectorTools
 } // namespace VectorTools
 
 
+// Make sure we can use NormType with Patterns.
+namespace Patterns
+{
+  namespace Tools
+  {
+    template <>
+    struct Convert<VectorTools::NormType, void>
+    {
+      /**
+       * Return the Correct pattern for NormType.
+       */
+      static std::unique_ptr<Patterns::PatternBase>
+      to_pattern()
+      {
+        return std_cxx14::make_unique<Patterns::Selection>(
+          "mean|L1_norm|L2_norm|Lp_norm|"
+          "Linfty_norm|H1_seminorm|Hdiv_seminorm|"
+          "H1_norm|W1p_seminorm|W1p_norm|"
+          "W1infty_seminorm|W1infty_norm");
+      }
+
+
+
+      /**
+       * Convert a NormType to a string.
+       */
+      static std::string
+      to_string(const VectorTools::NormType &                 s,
+                const std::unique_ptr<Patterns::PatternBase> &p =
+                  Convert<VectorTools::NormType>::to_pattern())
+      {
+        std::string str;
+        if (s == VectorTools::mean)
+          str = "mean";
+        else if (s == VectorTools::L1_norm)
+          str = "L1_norm";
+        else if (s == VectorTools::L2_norm)
+          str = "L2_norm";
+        else if (s == VectorTools::Lp_norm)
+          str = "Lp_norm";
+        else if (s == VectorTools::Linfty_norm)
+          str = "Linfty_norm";
+        else if (s == VectorTools::H1_seminorm)
+          str = "H1_seminorm";
+        else if (s == VectorTools::Hdiv_seminorm)
+          str = "Hdiv_seminorm";
+        else if (s == VectorTools::H1_norm)
+          str = "H1_norm";
+        else if (s == VectorTools::W1p_seminorm)
+          str = "W1p_seminorm";
+        else if (s == VectorTools::W1infty_seminorm)
+          str = "W1infty_seminorm";
+        else if (s == VectorTools::W1infty_norm)
+          str = "W1infty_norm";
+        else if (s == VectorTools::W1p_norm)
+          str = "W1p_norm";
+        else
+          {
+            AssertThrow(false, ExcMessage("Didn't recognize a norm type."));
+          }
+        AssertThrow(p->match(str), ExcInternalError());
+        return str;
+      }
+
+
+      /**
+       * Convert a string to a NormType.
+       */
+      static VectorTools::NormType
+      to_value(const std::string &                           str,
+               const std::unique_ptr<Patterns::PatternBase> &p =
+                 Convert<VectorTools::NormType>::to_pattern())
+      {
+        VectorTools::NormType norm = VectorTools::mean;
+        AssertThrow(p->match(str),
+                    ExcMessage(
+                      "String " + str +
+                      " cannot be converted to VectorTools::NormType"));
+
+        if (str == "mean")
+          norm = VectorTools::mean;
+        else if (str == "L1_norm")
+          norm = VectorTools::L1_norm;
+        else if (str == "L2_norm")
+          norm = VectorTools::L2_norm;
+        else if (str == "Lp_norm")
+          norm = VectorTools::Lp_norm;
+        else if (str == "Linfty_norm")
+          norm = VectorTools::Linfty_norm;
+        else if (str == "H1_seminorm")
+          norm = VectorTools::H1_seminorm;
+        else if (str == "Hdiv_seminorm")
+          norm = VectorTools::Hdiv_seminorm;
+        else if (str == "H1_norm")
+          norm = VectorTools::H1_norm;
+        else if (str == "W1p_seminorm")
+          norm = VectorTools::W1p_seminorm;
+        else if (str == "W1infty_seminorm")
+          norm = VectorTools::W1infty_seminorm;
+        else if (str == "W1infty_norm")
+          norm = VectorTools::W1infty_norm;
+        else if (str == "W1p_norm")
+          norm = VectorTools::W1p_norm;
+        else
+          {
+            AssertThrow(false, ExcMessage("Didn't recognize a norm type."));
+          }
+        return norm;
+      }
+    };
+  } // namespace Tools
+} // namespace Patterns
+
 DEAL_II_NAMESPACE_CLOSE
 
 #endif
index d955bb0b649d7d0a3d3f09fba1da876ece10725a..ef324daefe87ac27fae24bf73d5112cdac829c0c 100644 (file)
@@ -60,14 +60,14 @@ namespace
 
 
 ParsedConvergenceTable::ParsedConvergenceTable(
-  const std::vector<std::string> &solution_names,
-  const std::vector<std::set<ParsedConvergenceTableFlags::NormType>>
-    &list_of_error_norms)
+  const std::vector<std::string> &                    solution_names,
+  const std::vector<std::set<VectorTools::NormType>> &list_of_error_norms)
   : ParsedConvergenceTable(solution_names,
                            list_of_error_norms,
-                           {ParsedConvergenceTableFlags::cells,
-                            ParsedConvergenceTableFlags::dofs},
-                           ParsedConvergenceTableFlags::dofs,
+                           2.0,
+                           {"cells", "dofs"},
+                           "dofs",
+                           "reduction_rate_log2",
                            "",
                            3,
                            true,
@@ -77,27 +77,31 @@ ParsedConvergenceTable::ParsedConvergenceTable(
 
 
 ParsedConvergenceTable::ParsedConvergenceTable(
-  const std::vector<std::string> &component_names,
-  const std::vector<std::set<ParsedConvergenceTableFlags::NormType>>
-    &list_of_error_norms,
-  const std::set<ParsedConvergenceTableFlags::ExtraColumns> &extra_columns,
-  const ParsedConvergenceTableFlags::ExtraColumns &          rate_key,
-  const std::string &                                        error_file_name,
-  const unsigned int &                                       precision,
-  const bool &                                               compute_error,
-  const bool &                                               output_error)
+  const std::vector<std::string> &                    component_names,
+  const std::vector<std::set<VectorTools::NormType>> &list_of_error_norms,
+  const double &                                      exponent,
+  const std::set<std::string> &                       extra_columns,
+  const std::string &                                 rate_key,
+  const std::string &                                 rate_mode,
+  const std::string &                                 error_file_name,
+  const unsigned int &                                precision,
+  const bool &                                        compute_error,
+  const bool &                                        output_error)
   : component_names(component_names)
   , unique_component_names(get_unique_component_names(component_names))
   , unique_component_masks(get_unique_component_masks(component_names))
   , norms_per_unique_component(list_of_error_norms)
+  , exponent(exponent)
   , extra_columns(extra_columns)
   , rate_key(rate_key)
+  , rate_mode(rate_mode)
   , precision(precision)
   , error_file_name(error_file_name)
   , compute_error(compute_error)
   , output_error(output_error)
 {
-  AssertDimension(unique_component_names.size(), list_of_error_norms.size());
+  AssertDimension(norms_per_unique_component.size(),
+                  unique_component_names.size());
 }
 
 
@@ -132,16 +136,30 @@ ParsedConvergenceTable::add_parameters(ParameterHandler &prm)
     "and each norm by a comma. Implemented norms are Linfty, L2, "
     "W1infty, H1, and custom. If you want to skip a component, use none.");
 
+
+  prm.add_parameter("Exponent for p-norms",
+                    exponent,
+                    "The exponent to use when computing p-norms.",
+                    Patterns::Double(1));
+
   prm.add_parameter("Extra columns",
                     extra_columns,
                     "Extra columns to add to the table. Available options "
-                    "are dofs, cells, and dt.");
+                    "are dofs and cells.",
+                    Patterns::List(Patterns::Selection("dofs|cells")));
 
   prm.add_parameter("Rate key",
                     rate_key,
                     "Key to use when computing convergence rates. If "
-                    "this is set to a column that is not present, or to none, "
-                    "then no error rates are computed.");
+                    "this is set to a column that is not present, or to the "
+                    "empty string, then no error rates are computed.");
+
+  prm.add_parameter("Rate mode",
+                    rate_mode,
+                    "What type of error rate to compute. Available options are "
+                    "reduction_rate_log2, reduction_rate, and none.",
+                    Patterns::Selection(
+                      "reduction_rate|reduction_rate_log2|none"));
 }
 
 
@@ -152,7 +170,7 @@ ParsedConvergenceTable::output_table(std::ostream &out)
   if (compute_error)
     {
       // Add convergence rates if the rate_key is not empty
-      if (rate_key != ParsedConvergenceTableFlags::no_columns)
+      if (rate_key != "")
         {
           bool has_key = false;
           for (const auto &col : extra_columns)
@@ -160,14 +178,43 @@ ParsedConvergenceTable::output_table(std::ostream &out)
               if (rate_key == col)
                 has_key = true;
 
-              if (col != ParsedConvergenceTableFlags::no_columns)
+              if (col != "")
                 table.omit_column_from_convergence_rate_evaluation(
                   Patterns::Tools::to_string(col));
             }
+
+          for (const auto &extra_col : extra_column_functions)
+            if (extra_col.second.second)
+              {
+                if (rate_key == extra_col.first)
+                  has_key = true;
+                table.omit_column_from_convergence_rate_evaluation(
+                  extra_col.first);
+              }
+
           if (has_key)
-            table.evaluate_all_convergence_rates(
-              Patterns::Tools::to_string(rate_key),
-              ConvergenceTable::reduction_rate_log2);
+            {
+              if (rate_mode == "reduction_rate_log2")
+                table.evaluate_all_convergence_rates(
+                  Patterns::Tools::to_string(rate_key),
+                  ConvergenceTable::reduction_rate_log2);
+              else if (rate_mode == "reduction_rate")
+                table.evaluate_all_convergence_rates(
+                  Patterns::Tools::to_string(rate_key),
+                  ConvergenceTable::reduction_rate);
+              else
+                {
+                  Assert(rate_mode != "none", ExcInternalError());
+                }
+            }
+          else
+            {
+              AssertThrow(rate_key != "",
+                          ExcMessage(
+                            "You specified the key <" + rate_key +
+                            "> to compute convergence rates, but that key does "
+                            "not exist in the current table."));
+            }
         }
 
       if (output_error)
@@ -200,4 +247,16 @@ ParsedConvergenceTable::output_table(std::ostream &out)
         }
     }
 }
+
+
+
+void
+ParsedConvergenceTable::add_extra_column(
+  const std::string &            column_name,
+  const std::function<double()> &custom_function,
+  const bool &                   exclude_from_rates)
+{
+  extra_column_functions[column_name] = {custom_function, exclude_from_rates};
+}
+
 DEAL_II_NAMESPACE_CLOSE
index 0057e2c6f85c618a0a00c57adad7f46aaf449cd2..8a79e6dd2a0695ff1258e096ea65df3158a0a5bf 100644 (file)
@@ -47,13 +47,15 @@ main()
   FE_Q<2>       fe(1);
   DoFHandler<2> dh(tria);
 
+  Functions::CosineFunction<2> exact(1);
+
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
       Vector<double> sol(dh.n_dofs());
-      VectorTools::interpolate(dh, Functions::CosineFunction<2>(1), sol);
-      table.error_from_exact(dh, sol, Functions::CosineFunction<2>(1));
+      VectorTools::interpolate(dh, exact, sol);
+      table.error_from_exact(dh, sol, exact);
     }
   table.output_table(deallog.get_file_stream());
 }
index dda330200a61e3c3a0cb08a6d0234b0bc9409845..5e431ad0e4157d607ef69c49e77066ef7b3ffbcc 100644 (file)
@@ -1,7 +1,7 @@
 
-dofs cells    u_Linfty         u_L2           u_H1      
-9    4     1.183e-01 -    5.156e-02 -    2.615e-01 -    
-25   16    3.291e-02 2.50 1.333e-02 2.65 1.272e-01 1.41 
-81   64    8.449e-03 2.31 3.360e-03 2.34 6.313e-02 1.19 
-289  256   2.126e-03 2.17 8.418e-04 2.18 3.150e-02 1.09 
-1089 1024  5.325e-04 2.09 2.106e-04 2.09 1.574e-02 1.05 
+cells dofs   u_L2_norm    u_Linfty_norm    u_H1_norm    
+4     9    5.156e-02 -    1.183e-01 -    2.615e-01 -    
+16    25   1.333e-02 2.65 3.291e-02 2.50 1.272e-01 1.41 
+64    81   3.360e-03 2.34 8.449e-03 2.31 6.313e-02 1.19 
+256   289  8.418e-04 2.18 2.126e-03 2.17 3.150e-02 1.09 
+1024  1089 2.106e-04 2.09 5.325e-04 2.09 1.574e-02 1.05 
index 561d92693043d5b6d0abc38021a1e473209a59b9..6a5bfce2b9a4fac98d81f10cd9ab5f75e784554b 100644 (file)
@@ -3,6 +3,8 @@ DEAL:parameters::Enable computation of the errors: true
 DEAL:parameters::Enable output to streams: true
 DEAL:parameters::Error file name: 
 DEAL:parameters::Error precision: 3
-DEAL:parameters::Extra columns: dofs, cells
-DEAL:parameters::List of error norms to compute: Linfty, L2, H1
+DEAL:parameters::Exponent for p-norms: 2
+DEAL:parameters::Extra columns: cells, dofs
+DEAL:parameters::List of error norms to compute: L2_norm, Linfty_norm, H1_norm
 DEAL:parameters::Rate key: dofs
+DEAL:parameters::Rate mode: reduction_rate_log2
index 20b22cb24cb2837602b3e92d747d63294a780946..cc712f9ef391a374f376ca74a5ad0c5dc78fe53b 100644 (file)
@@ -39,8 +39,8 @@ main()
   initlog();
 
   ParsedConvergenceTable table({"u", "v"},
-                               {{ParsedConvergenceTableFlags::L2},
-                                {ParsedConvergenceTableFlags::H1}});
+                               {{VectorTools::L2_norm},
+                                {VectorTools::H1_norm}});
 
   ParameterHandler prm;
   table.add_parameters(prm);
@@ -48,16 +48,17 @@ main()
   Triangulation<2> tria;
   GridGenerator::hyper_cube(tria);
 
-  FESystem<2>   fe(FE_Q<2>(1), 2);
-  DoFHandler<2> dh(tria);
+  FESystem<2>                  fe(FE_Q<2>(1), 2);
+  DoFHandler<2>                dh(tria);
+  Functions::CosineFunction<2> exact(2);
 
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
       Vector<double> sol(dh.n_dofs());
-      VectorTools::interpolate(dh, Functions::CosineFunction<2>(2), sol);
-      table.error_from_exact(dh, sol, Functions::CosineFunction<2>(2));
+      VectorTools::interpolate(dh, exact, sol);
+      table.error_from_exact(dh, sol, exact);
     }
   table.output_table(deallog.get_file_stream());
 }
index 62170103fc415bca3d2ef27c57bce1889278ff02..711d333342de210c142a607ed089546457a4baf3 100644 (file)
@@ -1,7 +1,7 @@
 
-dofs cells      u_L2           v_H1      
-18   4     5.156e-02 -    2.615e-01 -    
-50   16    1.333e-02 2.65 1.272e-01 1.41 
-162  64    3.360e-03 2.34 6.313e-02 1.19 
-578  256   8.418e-04 2.18 3.150e-02 1.09 
-2178 1024  2.106e-04 2.09 1.574e-02 1.05 
+cells dofs   u_L2_norm      v_H1_norm    
+4     18   5.156e-02 -    2.615e-01 -    
+16    50   1.333e-02 2.65 1.272e-01 1.41 
+64    162  3.360e-03 2.34 6.313e-02 1.19 
+256   578  8.418e-04 2.18 3.150e-02 1.09 
+1024  2178 2.106e-04 2.09 1.574e-02 1.05 
index 3e00ece7bc3ef64268d40c2f5f18dfa86fbc38be..fa7132da1d11e941f2b0c7f3bbfb6a4367dca691 100644 (file)
@@ -38,7 +38,7 @@ main()
 {
   initlog();
 
-  ParsedConvergenceTable table({"u", "u"}, {{ParsedConvergenceTableFlags::L2}});
+  ParsedConvergenceTable table({"u", "u"}, {{VectorTools::L2_norm}});
 
   ParameterHandler prm;
   table.add_parameters(prm);
@@ -46,16 +46,17 @@ main()
   Triangulation<2> tria;
   GridGenerator::hyper_cube(tria);
 
-  FESystem<2>   fe(FE_Q<2>(1), 2);
-  DoFHandler<2> dh(tria);
+  FESystem<2>                  fe(FE_Q<2>(1), 2);
+  DoFHandler<2>                dh(tria);
+  Functions::CosineFunction<2> exact(2);
 
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
       Vector<double> sol(dh.n_dofs());
-      VectorTools::interpolate(dh, Functions::CosineFunction<2>(2), sol);
-      table.error_from_exact(dh, sol, Functions::CosineFunction<2>(2));
+      VectorTools::interpolate(dh, exact, sol);
+      table.error_from_exact(dh, sol, exact);
     }
   table.output_table(deallog.get_file_stream());
 }
index 1d09679cb411e28e9a18f9643dbe91a077d33203..d741b3bcde976a512fa8975fd8e8bf72668619c7 100644 (file)
@@ -1,7 +1,7 @@
 
-dofs cells      u_L2      
-18   4     7.291e-02 -    
-50   16    1.885e-02 2.65 
-162  64    4.752e-03 2.34 
-578  256   1.190e-03 2.18 
-2178 1024  2.978e-04 2.09 
+cells dofs   u_L2_norm    
+4     18   7.291e-02 -    
+16    50   1.885e-02 2.65 
+64    162  4.752e-03 2.34 
+256   578  1.190e-03 2.18 
+1024  2178 2.978e-04 2.09 
index 8cfb65071a912117becdfb9fcfd5875e08ed5f17..e2970a3d70b312b7db08433c8b284c3bcb8ac668 100644 (file)
@@ -39,8 +39,8 @@ main()
   initlog();
 
   ParsedConvergenceTable table({"u", "u", "p"},
-                               {{ParsedConvergenceTableFlags::H1},
-                                {ParsedConvergenceTableFlags::L2}});
+                               {{VectorTools::H1_norm},
+                                {VectorTools::L2_norm}});
 
   ParameterHandler prm;
   table.add_parameters(prm);
@@ -51,13 +51,15 @@ main()
   FESystem<2>   fe(FE_Q<2>(1), 3);
   DoFHandler<2> dh(tria);
 
+  Functions::CosineFunction<2> exact(3);
+
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
       Vector<double> sol(dh.n_dofs());
-      VectorTools::interpolate(dh, Functions::CosineFunction<2>(3), sol);
-      table.error_from_exact(dh, sol, Functions::CosineFunction<2>(3));
+      VectorTools::interpolate(dh, exact, sol);
+      table.error_from_exact(dh, sol, exact);
     }
   table.output_table(deallog.get_file_stream());
 }
index 1cc8dca7fc0addc8d025d2af0c79f150aef4d79a..c78d698078c12c190592a2379e536147532874f2 100644 (file)
@@ -1,7 +1,7 @@
 
-dofs cells      u_H1           p_L2      
-27   4     3.699e-01 -    5.156e-02 -    
-75   16    1.799e-01 1.41 1.333e-02 2.65 
-243  64    8.927e-02 1.19 3.360e-03 2.34 
-867  256   4.455e-02 1.09 8.418e-04 2.18 
-3267 1024  2.226e-02 1.05 2.106e-04 2.09 
+cells dofs   u_H1_norm      p_L2_norm    
+4     27   3.699e-01 -    5.156e-02 -    
+16    75   1.799e-01 1.41 1.333e-02 2.65 
+64    243  8.927e-02 1.19 3.360e-03 2.34 
+256   867  4.455e-02 1.09 8.418e-04 2.18 
+1024  3267 2.226e-02 1.05 2.106e-04 2.09 
index 0bf129ea0d9024f24a3dc2a9163dc3157753a9bb..0f26c7966c1624eb4560169e5e4fdc41c05bc75d 100644 (file)
 int
 main()
 {
-  initlog();
+  initlog(1);
 
-  ParsedConvergenceTable table({"u", "u", "p"},
-                               {{ParsedConvergenceTableFlags::H1},
-                                {ParsedConvergenceTableFlags::none}});
+  ParsedConvergenceTable table({"u", "u", "p"}, {{VectorTools::H1_norm}, {}});
 
   ParameterHandler prm;
   table.add_parameters(prm);
@@ -51,13 +49,15 @@ main()
   FESystem<2>   fe(FE_Q<2>(1), 3);
   DoFHandler<2> dh(tria);
 
+  Functions::CosineFunction<2> exact(3);
+
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
       Vector<double> sol(dh.n_dofs());
-      VectorTools::interpolate(dh, Functions::CosineFunction<2>(3), sol);
-      table.error_from_exact(dh, sol, Functions::CosineFunction<2>(3));
+      VectorTools::interpolate(dh, exact, sol);
+      table.error_from_exact(dh, sol, exact);
     }
   table.output_table(deallog.get_file_stream());
 }
index 07e887e86c57f06866767aca09da5e902cbca8a9..5d4cec934c54fa0b382ce9739ded550ca9498948 100644 (file)
@@ -1,7 +1,7 @@
 
-dofs cells      u_H1      
-27   4     3.699e-01 -    
-75   16    1.799e-01 1.41 
-243  64    8.927e-02 1.19 
-867  256   4.455e-02 1.09 
-3267 1024  2.226e-02 1.05 
+cells dofs   u_H1_norm    
+4     27   3.699e-01 -    
+16    75   1.799e-01 1.41 
+64    243  8.927e-02 1.19 
+256   867  4.455e-02 1.09 
+1024  3267 2.226e-02 1.05 
index 81a216edf0131ab43767aa9dd73e433e3302f764..a8194fc14514f589a2cb7d57cbf2fe1a1cd94b1d 100644 (file)
@@ -38,7 +38,7 @@ main()
 {
   initlog();
 
-  ParsedConvergenceTable table({"u"}, {{ParsedConvergenceTableFlags::custom}});
+  ParsedConvergenceTable table({"u"}, {{}});
 
   ParameterHandler prm;
   table.add_parameters(prm);
@@ -49,12 +49,16 @@ main()
   FESystem<2>   fe(FE_Q<2>(1), 1);
   DoFHandler<2> dh(tria);
 
+  Functions::CosineFunction<2> exact(1);
+
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
-      auto cycle = [&](const unsigned int) { return (i + 1) * 1.0; };
-      table.custom_error(cycle, dh, "cycle", true);
+      Vector<double> sol(dh.n_dofs());
+      auto           cycle = [&]() { return (i + 1) * 1.0; };
+      table.add_extra_column("cycle", cycle);
+      table.error_from_exact(dh, sol, exact);
     }
   table.output_table(deallog.get_file_stream());
 }
index fe2d44fefab513dd1318c55bf36879ab7ff03741..5648c34f961d6fc8bb1d93d20f8f295c8a81e4f0 100644 (file)
@@ -1,7 +1,7 @@
 
-dofs cells     u_cycle     
-9    4     1.000e+00 -     
-25   16    2.000e+00 -1.36 
-81   64    3.000e+00 -0.69 
-289  256   4.000e+00 -0.45 
-1089 1024  5.000e+00 -0.34 
+cells dofs      cycle      
+4     9    1.000e+00 -     
+16    25   2.000e+00 -1.36 
+64    81   3.000e+00 -0.69 
+256   289  4.000e+00 -0.45 
+1024  1089 5.000e+00 -0.34 
index cbe4ee356211655a21c7b51c861f4049eb1ee8e2..2d0be867b67f96a550cf7ba2d67e47817d7aa12e 100644 (file)
@@ -38,12 +38,12 @@ main()
 {
   initlog();
 
-  ParsedConvergenceTable table({"u"}, {{ParsedConvergenceTableFlags::custom}});
+  ParsedConvergenceTable table({"u"}, {{}});
 
   ParameterHandler prm;
   table.add_parameters(prm);
 
-  std::string input = "set Extra columns = none\n";
+  std::string input = "set Extra columns = \n";
 
   prm.parse_input_from_string(input);
 
@@ -53,12 +53,17 @@ main()
   FESystem<2>   fe(FE_Q<2>(1), 1);
   DoFHandler<2> dh(tria);
 
+  Functions::CosineFunction<2> exact(1);
+
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
-      auto cycle = [&](const unsigned int) { return (i + 1) * 1.0; };
-      table.custom_error(cycle, dh, "cycle", true);
+      Vector<double> sol(dh.n_dofs());
+
+      auto cycle = [&]() { return (i + 1) * 1.0; };
+      table.add_extra_column("cycle", cycle);
+      table.error_from_exact(dh, sol, exact);
     }
   table.output_table(deallog.get_file_stream());
 }
index 1a27569374e1a5fd35feb91a864b3c913878ece5..c59dd3911deafe6eebf0e098f37a5733393d323a 100644 (file)
@@ -1,5 +1,5 @@
 
- u_cycle  
+  cycle   
 1.000e+00 
 2.000e+00 
 3.000e+00 
index 05a07c62459b7e0a4abd91b1f414da99088d600e..db0c0aad233c3a7c92a4b0cabc2bb24782dbead3 100644 (file)
@@ -38,12 +38,12 @@ main()
 {
   initlog();
 
-  ParsedConvergenceTable table({"u"}, {{ParsedConvergenceTableFlags::custom}});
+  ParsedConvergenceTable table({"u"}, {{}});
 
   ParameterHandler prm;
   table.add_parameters(prm);
 
-  std::string input = "set Extra columns = dt\n"
+  std::string input = "set Extra columns = \n"
                       "set Rate key = dt\n";
 
   prm.parse_input_from_string(input);
@@ -54,12 +54,20 @@ main()
   FESystem<2>   fe(FE_Q<2>(1), 1);
   DoFHandler<2> dh(tria);
 
+  Functions::CosineFunction<2> exact(1);
+
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
-      auto cycle = [&](const unsigned int) { return (i + 1) * 1.0; };
-      table.custom_error(cycle, dh, "cycle", true, 1.0 / (i * i + 1));
+      Vector<double> sol(dh.n_dofs());
+
+      auto cycle = [&]() { return (i + 1) * 1.0; };
+      auto dt    = [&]() { return 1.0 / (i * i + 1); };
+
+      table.add_extra_column("cycle", cycle);
+      table.add_extra_column("dt", dt);
+      table.error_from_exact(dh, sol, exact);
     }
   table.output_table(deallog.get_file_stream());
 }
index 9b5f696c0da9e7c4a3a99634d3f308dae4935e54..31787d7683ede482be9596f4027dbd7417277578 100644 (file)
@@ -1,7 +1,7 @@
 
-  dt      u_cycle     
-1.0000 1.000e+00 -    
-0.5000 2.000e+00 2.00 
-0.2000 3.000e+00 0.89 
-0.1000 4.000e+00 0.83 
-0.0588 5.000e+00 0.84 
+  cycle      dt     
+1.000e+00 1.000e+00 
+2.000e+00 5.000e-01 
+3.000e+00 2.000e-01 
+4.000e+00 1.000e-01 
+5.000e+00 5.882e-02 
index af3c9a43ee34f66728477600779a6f3652215891..cb3c5ca8381de94ce1a0d874e6a6e23e8bca0ad1 100644 (file)
@@ -38,13 +38,13 @@ main()
 {
   initlog();
 
-  ParsedConvergenceTable table({"u"}, {{ParsedConvergenceTableFlags::custom}});
+  ParsedConvergenceTable table({"u"}, {{}});
 
   ParameterHandler prm;
   table.add_parameters(prm);
 
-  std::string input = "set Extra columns = dt, dofs, cells\n"
-                      "set Rate key = cells\n"
+  std::string input = "set Extra columns = dofs, cells\n"
+                      "set Rate key = dt\n"
                       "set Enable output to streams = false\n";
 
   prm.parse_input_from_string(input);
@@ -55,14 +55,20 @@ main()
   FESystem<2>   fe(FE_Q<2>(1), 1);
   DoFHandler<2> dh(tria);
 
+  Functions::CosineFunction<2> exact(1);
+
   for (unsigned int i = 0; i < 5; ++i)
     {
       tria.refine_global(1);
       dh.distribute_dofs(fe);
-      auto cycle = [&](const unsigned int) {
-        return 1.0 / ((i + 1) * (i + 1));
-      };
-      table.custom_error(cycle, dh, "cycle", true, i + 1);
+      Vector<double> sol(dh.n_dofs());
+
+      auto cycle = [&]() { return (i + 1) * 1.0; };
+      auto dt    = [&]() { return i + 1.0; };
+
+      table.add_extra_column("cycle", cycle);
+      table.add_extra_column("dt", dt, true);
+      table.error_from_exact(dh, sol, exact);
     }
 
   input = "set Error file name = error.txt\n";
index f1d7508a0ead8408ef3846f31ba109e3aca58aef..d33f4d1576ac48abadd4f97a30c8c8abbfc67183 100644 (file)
@@ -1,17 +1,17 @@
 
-dofs cells   dt      u_cycle     
-   9     4 1.0000 1.000e+00    - 
-  25    16 2.0000 2.500e-01 2.00 
-  81    64 3.0000 1.111e-01 1.17 
- 289   256 4.0000 6.250e-02 0.83 
-1089  1024 5.0000 4.000e-02 0.64 
+cells dofs      cycle         dt     
+    4    9 1.000e+00     - 1.000e+00 
+   16   25 2.000e+00 -2.00 2.000e+00 
+   64   81 3.000e+00 -2.00 3.000e+00 
+  256  289 4.000e+00 -2.00 4.000e+00 
+ 1024 1089 5.000e+00 -2.00 5.000e+00 
 
-| dofs | cells | dt     | u_cycle   | u_cycle...red.rate.log2 | 
-| 9    | 4     | 1.0000 | 1.000e+00 | -                       | 
-| 25   | 16    | 2.0000 | 2.500e-01 | 2.00                    | 
-| 81   | 64    | 3.0000 | 1.111e-01 | 1.17                    | 
-| 289  | 256   | 4.0000 | 6.250e-02 | 0.83                    | 
-| 1089 | 1024  | 5.0000 | 4.000e-02 | 0.64                    | 
+| cells | dofs | cycle     | cycle...red.rate.log2 | dt        | 
+| 4     | 9    | 1.000e+00 | -                     | 1.000e+00 | 
+| 16    | 25   | 2.000e+00 | -2.00                 | 2.000e+00 | 
+| 64    | 81   | 3.000e+00 | -2.00                 | 3.000e+00 | 
+| 256   | 289  | 4.000e+00 | -2.00                 | 4.000e+00 | 
+| 1024  | 1089 | 5.000e+00 | -2.00                 | 5.000e+00 | 
 
 \documentclass[10pt]{report}
 \usepackage{float}
@@ -20,14 +20,14 @@ dofs cells   dt      u_cycle
 \begin{document}
 \begin{table}[H]
 \begin{center}
-\begin{tabular}{|r|r|r|c|c|} \hline
-\# dofs & \# cells & \Delta t & 
-\multicolumn{2}{|c|}{$\| u - u_h \|_{\text{cycle} $}\\ \hline
-9 & 4 & 1.0000 & 1.000e+00 & -\\ \hline
-25 & 16 & 2.0000 & 2.500e-01 & 2.00\\ \hline
-81 & 64 & 3.0000 & 1.111e-01 & 1.17\\ \hline
-289 & 256 & 4.0000 & 6.250e-02 & 0.83\\ \hline
-1089 & 1024 & 5.0000 & 4.000e-02 & 0.64\\ \hline
+\begin{tabular}{|r|r|c|c|c|} \hline
+\# cells & \# dofs & 
+\multicolumn{2}{|c|}{cycle} & dt\\ \hline
+4 & 9 & 1.000e+00 & - & 1.000e+00\\ \hline
+16 & 25 & 2.000e+00 & -2.00 & 2.000e+00\\ \hline
+64 & 81 & 3.000e+00 & -2.00 & 3.000e+00\\ \hline
+256 & 289 & 4.000e+00 & -2.00 & 4.000e+00\\ \hline
+1024 & 1089 & 5.000e+00 & -2.00 & 5.000e+00\\ \hline
 \end{tabular}
 \end{center}
 \end{table}

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.