deal2lkit: A ToolKit library for Deal.II
error_handler.h
Go to the documentation of this file.
1 //-----------------------------------------------------------
2 //
3 // Copyright (C) 2014 - 2015 by the deal2lkit authors
4 //
5 // This file is part of the deal2lkit library.
6 //
7 // The deal2lkit library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal2lkit distribution.
13 //
14 //-----------------------------------------------------------
15 
16 #ifndef _d2k_error_handler_h
17 #define _d2k_error_handler_h
18 
19 #include <deal2lkit/config.h>
20 #include <fstream>
21 
24 #include <deal.II/lac/vector.h>
25 
26 #include <deal.II/grid/tria.h>
27 
28 // #include <deal.II/numerics/error_estimator.h>
29 #include <deal.II/base/function.h>
32 
34 #include <deal.II/base/logstream.h>
35 #include <deal.II/base/config.h>
36 
37 
39 #include <deal.II/base/utilities.h>
40 
42 
44 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
46 DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
48 #include <deal.II/fe/mapping_q.h>
49 #include <deal.II/fe/fe.h>
50 
53 
55 #include <map>
56 #include <cstdio>
57 #include <iostream>
58 #include <fstream>
59 #include <vector>
60 #include <string>
61 
62 
63 #include <functional>
64 
65 using namespace dealii;
66 
67 D2K_NAMESPACE_OPEN
68 
70 {
71  None = 0x00,
72  Linfty = 0x01,
73  L2 = 0x02,
74  W1infty = 0x04,
75  H1 = 0x08,
76  AddUp = 0x10,
77  Custom = 0x20
78 };
79 
80 
81 template <int ntables=1>
83 {
84 public:
87  ErrorHandler (const std::string name="",
88  const std::string solution_names = "u",
89  const std::string list_of_error_norms = "Linfty, L2, H1");
90 
92  virtual void declare_parameters(ParameterHandler &prm);
93 
95  virtual void parse_parameters(ParameterHandler &prm);
96 
99  template<typename DH, typename VEC>
100  void error_from_exact(const DH &vspace,
101  const VEC &solution,
102  const Function<DH::space_dimension> &exact,
103  unsigned int table_no = 0,
104  double dt=0.);
105 
106 
108  template<typename DH, typename VEC>
109  void error_from_exact(const Mapping<DH::dimension,DH::space_dimension> &mapping,
110  const DH &vspace,
111  const VEC &solution,
112  const Function<DH::space_dimension> &exact,
113  unsigned int table_no = 0,
114  double dt=0.);
115 
116 
127  template<typename DH>
128  void custom_error(const std::function<double(const unsigned int component)> &custom_error_function,
129  const DH &dh,
130  const std::string &error_name="custom",
131  const bool add_table_extras = false,
132  const unsigned int table_no = 0,
133  const double dt=0.);
134 
136  template<typename DH, typename VEC>
137  void difference(const DH &, const VEC &,
138  const DH &, const VEC &,
139  unsigned int table_no = 0, double dt=0.);
140 
142  template<typename DH, typename VEC>
143  void difference(const DH &, const VEC &,
144  const VEC &, unsigned int table_no = 0, double dt=0.);
145 
147  void output_table(std::ostream &out=std::cout, const unsigned int table_no=0);
148 
151  void output_table(ConditionalOStream &pcout, const unsigned int table_no=0);
152 
153 private:
155  const std::string solution_names;
156 
158  const std::string list_of_error_norms;
159 
161  std::vector<ConvergenceTable> tables;
162 
165  std::vector<std::string> headers;
166 
169  std::vector<std::string> latex_headers;
170 
172  std::vector<std::string> latex_captions;
173 
175  std::vector<std::string> names;
176 
178  std::vector<std::vector<NormFlags> > types;
179 
182 
186 
188  std::vector<bool> add_rates;
189 
192 
195 
197  std::string error_file_format;
198 
200  std::vector<std::map<std::string, bool> > extras;
201 
203  std::vector<std::string> rate_keys;
204 
206  unsigned int precision;
207 };
208 
217 inline
218 NormFlags
220 {
221  return static_cast<NormFlags> (
222  static_cast<unsigned int> (f1) |
223  static_cast<unsigned int> (f2));
224 }
225 
230 inline
231 NormFlags &
233 {
234  f1 = f1 | f2;
235  return f1;
236 }
237 
238 
247 inline
248 NormFlags
250 {
251  return static_cast<NormFlags> (
252  static_cast<unsigned int> (f1) &
253  static_cast<unsigned int> (f2));
254 }
255 
256 
261 inline
262 NormFlags &
264 {
265  f1 = f1 & f2;
266  return f1;
267 }
268 
269 // ============================================================
270 // Template instantiations
271 // ============================================================
272 
273 
274 template <int ntables>
275 template<typename DH, typename VECTOR>
277  const VECTOR &solution1,
278  const VECTOR &solution2,
279  unsigned int table_no,
280  double dt)
281 {
282  AssertThrow(solution1.size() == solution2.size(), ExcDimensionMismatch(
283  solution1.size(), solution2.size()));
284  VECTOR solution(solution1);
285  solution -= solution2;
286  error_from_exact(dh, solution,
287  ConstantFunction<DH::space_dimension>(0, headers.size()), table_no, dt);
288 }
289 
290 
291 
292 template <int ntables>
293 template<typename DH, typename VECTOR>
295  const VECTOR &solution,
296  const Function<DH::space_dimension> &exact,
297  unsigned int table_no,
298  double dt)
299 {
301  dh, solution, exact, table_no, dt);
302 }
303 
304 template <int ntables>
305 template<typename DH, typename VECTOR>
307  const DH &dh,
308  const VECTOR &solution,
309  const Function<DH::space_dimension> &exact,
310  unsigned int table_no,
311  double dt)
312 {
313  const int dim=DH::dimension;
314  const int spacedim=DH::space_dimension;
315  if (compute_error)
316  {
317  AssertThrow(initialized, ExcNotInitialized());
318  AssertThrow(table_no < types.size(), ExcIndexRange(table_no, 0, names.size()));
319  AssertThrow(exact.n_components == types[table_no].size(),
320  ExcDimensionMismatch(exact.n_components, types[table_no].size()));
321 
322  std::vector< std::vector<double> > error( exact.n_components, std::vector<double>(4));
323  const unsigned int n_active_cells = dh.get_triangulation().n_global_active_cells();
324  const unsigned int n_dofs=dh.n_dofs();
325 
326  if (extras[table_no]["cells"])
327  {
328  tables[table_no].add_value("cells", n_active_cells);
329  tables[table_no].set_tex_caption("cells", "\\# cells");
330  tables[table_no].set_tex_format("cells", "r");
331  }
332  if (extras[table_no]["dofs"])
333  {
334  tables[table_no].add_value("dofs", n_dofs);
335  tables[table_no].set_tex_caption("dofs", "\\# dofs");
336  tables[table_no].set_tex_format("dofs", "r");
337  }
338  if (extras[table_no]["dt"])
339  {
340  tables[table_no].add_value("dt", dt);
341  tables[table_no].set_tex_caption("dt", "\\Delta t");
342  tables[table_no].set_tex_format("dt", "r");
343  }
344 
345  bool compute_Linfty = false;
346  bool compute_L2 = false;
347  bool compute_W1infty = false;
348  bool compute_H1 = false;
349  bool add_this = false;
350 
351  unsigned int last_non_add = 0;
352 
353  for (unsigned int component=0; component < exact.n_components; ++component)
354  {
355  NormFlags norm = types[table_no][component];
356 
357  // Select one Component
358  ComponentSelectFunction<spacedim> select_component ( component, 1. , exact.n_components);
359 
360  Vector<float> difference_per_cell (dh.get_triangulation().n_global_active_cells());
361 
362  QGauss<dim> q_gauss((dh.get_fe().degree+1) * 2);
363 
364  // The add bit is set
365  add_this = (norm & AddUp);
366 
367  if (!add_this)
368  {
369  last_non_add = component;
370  compute_L2 = ( norm & L2 );
371  compute_H1 = ( norm & H1 );
372  compute_W1infty = ( norm & W1infty ) ;
373  compute_Linfty = ( norm & Linfty );
374  }
375  // if add is set, we do not modify the previous selection
376 
377  if (compute_L2)
378  {
380  mapping,
381  dh,
382  solution,
383  exact,
384  difference_per_cell,
385  q_gauss,
386  VectorTools::L2_norm,
387  &select_component );
388  }
389 
390  const double L2_error = difference_per_cell.l2_norm();
391  difference_per_cell = 0;
392 
393  if (compute_H1)
394  {
396  mapping,
397  dh, //dof_handler,
398  solution,
399  exact,
400  difference_per_cell,
401  q_gauss,
402  VectorTools::H1_norm,
403  &select_component );
404  }
405  const double H1_error = difference_per_cell.l2_norm();
406  difference_per_cell = 0;
407 
408  if (compute_W1infty)
409  {
411  mapping,
412  dh, //dof_handler,
413  solution,
414  exact,
415  difference_per_cell,
416  q_gauss,
417  VectorTools::W1infty_norm,
418  &select_component );
419  }
420 
421  const double W1inf_error = difference_per_cell.linfty_norm();
422 
423  if (compute_Linfty)
424  {
426  mapping,
427  dh, //dof_handler,
428  solution,
429  exact,
430  difference_per_cell,
431  q_gauss,
432  VectorTools::Linfty_norm,
433  &select_component );
434  }
435 
436  const double Linf_error = difference_per_cell.linfty_norm();
437 
438  if (add_this)
439  {
440  AssertThrow(component, ExcMessage("Cannot add on first component!"));
441 
442  error[last_non_add][0] = std::max(error[last_non_add][0], Linf_error);
443  error[last_non_add][1] += L2_error;
444  error[last_non_add][2] = std::max(error[last_non_add][2], W1inf_error);
445  error[last_non_add][3] += H1_error;
446 
447  }
448  else
449  {
450 
451  error[component][0] = Linf_error;
452  error[component][1] = L2_error;
453  error[component][2] = W1inf_error;
454  error[component][3] = H1_error;
455 
456  }
457  }
458 
459  for (unsigned int j=0; j<exact.n_components; ++j)
460  {
461  NormFlags norm = types[table_no][j];
462  // If this was added, don't do anything
463  if ( !(norm & AddUp) )
464  {
465  if (norm & Linfty)
466  {
467  std::string name = headers[j] + "_Linfty";
468  std::string latex_name = "$\\| " +
469  latex_headers[j] + " - " +
470  latex_headers[j] +"_h \\|_\\infty $";
471  double this_error = error[j][0];
472 
473  tables[table_no].add_value(name, this_error);
474  tables[table_no].set_precision(name, precision);
475  tables[table_no].set_scientific(name, true);
476  tables[table_no].set_tex_caption(name, latex_name);
477  }
478 
479  if (norm & L2)
480  {
481  std::string name = headers[j] + "_L2";
482  std::string latex_name = "$\\| " +
483  latex_headers[j] + " - " +
484  latex_headers[j] +"_h \\|_0 $";
485  double this_error = error[j][1];
486 
487  tables[table_no].add_value(name, this_error);
488  tables[table_no].set_precision(name, precision);
489  tables[table_no].set_scientific(name, true);
490  tables[table_no].set_tex_caption(name, latex_name);
491  }
492  if (norm & W1infty)
493  {
494  std::string name = headers[j] + "_W1infty";
495  std::string latex_name = "$\\| " +
496  latex_headers[j] + " - " +
497  latex_headers[j] +"_h \\|_{1,\\infty} $";
498  double this_error = error[j][2];
499 
500  tables[table_no].add_value(name, this_error);
501  tables[table_no].set_precision(name, precision);
502  tables[table_no].set_scientific(name, true);
503  tables[table_no].set_tex_caption(name, latex_name);
504  }
505  if (norm & H1)
506  {
507  std::string name = headers[j] + "_H1";
508  std::string latex_name = "$\\| " +
509  latex_headers[j] + " - " +
510  latex_headers[j] +"_h \\|_1 $";
511  double this_error = error[j][3];
512 
513  tables[table_no].add_value(name, this_error);
514  tables[table_no].set_precision(name, precision);
515  tables[table_no].set_scientific(name, true);
516  tables[table_no].set_tex_caption(name, latex_name);
517  }
518  }
519  }
520  }
521 }
522 
523 
524 
525 template <int ntables>
526 template<typename DH>
527 void ErrorHandler<ntables>::custom_error(const std::function<double(const unsigned int component)> &custom_error_function,
528  const DH &dh,
529  const std::string &error_name,
530  const bool add_table_extras,
531  const unsigned int table_no,
532  const double dt)
533 {
534  if (compute_error)
535  {
536  AssertThrow(initialized, ExcNotInitialized());
537  AssertThrow(table_no < types.size(), ExcIndexRange(table_no, 0, types.size()));
538 
539  const unsigned int n_components = types.size();
540  std::vector<double> c_error( types[table_no].size() );
541  const unsigned int n_active_cells = dh.get_triangulation().n_global_active_cells();
542  const unsigned int n_dofs=dh.n_dofs();
543  if (add_table_extras)
544  {
545  if (extras[table_no]["cells"])
546  {
547  tables[table_no].add_value("cells", n_active_cells);
548  tables[table_no].set_tex_caption("cells", "\\# cells");
549  tables[table_no].set_tex_format("cells", "r");
550  }
551  if (extras[table_no]["dofs"])
552  {
553  tables[table_no].add_value("dofs", n_dofs);
554  tables[table_no].set_tex_caption("dofs", "\\# dofs");
555  tables[table_no].set_tex_format("dofs", "r");
556  }
557  if (extras[table_no]["dt"])
558  {
559  tables[table_no].add_value("dt", dt);
560  tables[table_no].set_tex_caption("dt", "\\Delta t");
561  tables[table_no].set_tex_format("dt", "r");
562  }
563  }
564 
565  bool add_this = false;
566  bool compute_Custom = false;
567 
568  unsigned int last_non_add = 0;
569 
570  for (unsigned int component=0; component < n_components; ++component)
571  {
572  NormFlags norm = types[table_no][component];
573 
574  // The add bit is set
575  add_this = (norm & AddUp);
576 
577  if (!add_this)
578  compute_Custom = ( norm & Custom );
579  // if add is set, we do not modify the previous selection
580 
581  double Custom_error = 0;
582 
583  if (compute_Custom)
584  Custom_error = custom_error_function(component);
585 
586  if (add_this)
587  {
588  AssertThrow(component, ExcMessage("Cannot add on first component!"));
589 
590  c_error[last_non_add] += Custom_error;
591  }
592  else
593  {
594  c_error[last_non_add] = Custom_error;
595  }
596  }
597 
598  for (unsigned int j=0; j<n_components; ++j)
599  {
600  NormFlags norm = types[table_no][j];
601  // If this was added, don't do anything
602  if ( !(norm & AddUp) )
603  {
604  if (norm & Custom)
605  {
606  std::string name = headers[j] + "_" +error_name;
607  std::string latex_name = "$\\| " +
608  latex_headers[j] + " - " +
609  latex_headers[j] +"_h \\|_{\text{"+error_name+"} $";
610  double this_error = c_error[j];
611 
612  tables[table_no].add_value(name, this_error);
613  tables[table_no].set_precision(name, precision);
614  tables[table_no].set_scientific(name, true);
615  tables[table_no].set_tex_caption(name, latex_name);
616  }
617  }
618  }
619  }
620 }
621 
622 
623 
624 D2K_NAMESPACE_CLOSE
625 
626 #endif
void custom_error(const std::function< double(const unsigned int component)> &custom_error_function, const DH &dh, const std::string &error_name="custom", const bool add_table_extras=false, const unsigned int table_no=0, const double dt=0.)
Call the given custom function to compute the custom error for the given component and store the resu...
A parameter acceptor base class.
NormFlags & operator|=(NormFlags &f1, NormFlags f2)
Global operator which sets the bits from the second argument also in the first one.
bool compute_error
Compute the error.
std::vector< ConvergenceTable > tables
Error results.
static::ExceptionBase & ExcNotInitialized()
#define AssertThrow(cond, exc)
NormFlags & operator&=(NormFlags &f1, NormFlags f2)
Global operator which clears all the bits in the first argument if they are not also set in the secon...
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
NormFlags operator&(NormFlags f1, NormFlags f2)
Global operator which returns an object in which all bits are set which are set in the first as well ...
void difference(const DH &, const VEC &, const DH &, const VEC &, unsigned int table_no=0, double dt=0.)
Difference between two solutions in two different vector spaces.
const unsigned int n_components
std::vector< std::vector< NormFlags > > types
Type of error to compute per components.
static::ExceptionBase & ExcMessage(std::string arg1)
const std::string list_of_error_norms
List of error norms to compute.
unsigned int precision
The precision with which the table is written.
std::string error_file_format
The error file format.
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
bool output_error
Output the error file also on screen.
std::vector< std::string > latex_headers
Headers for latex tables.
std::vector< std::string > headers
Headers for tables and output.
bool initialized
The parameters have been read.
std::vector< std::map< std::string, bool > > extras
The extra column to add to the tables.
double norm(const FEValuesBase< dim > &fe, const VectorSlice< const std::vector< std::vector< Tensor< 1, dim > > > > &Du)
std::vector< std::string > rate_keys
Wether or not to calculate the rates according to the given keys.
std::vector< std::string > names
Names of the tables.
void error_from_exact(const DH &vspace, const VEC &solution, const Function< DH::space_dimension > &exact, unsigned int table_no=0, double dt=0.)
Calculate the error of the numeric solution in variuous norms.
NormFlags operator|(NormFlags f1, NormFlags f2)
Global operator which returns an object in which all bits are set which are either set in the first o...
std::vector< std::string > latex_captions
Captions for latex.
std::vector< bool > add_rates
Add convergence rates.
NormFlags
Definition: error_handler.h:69
bool write_error
Write the error files.
const std::string solution_names
Value of solution names.
void integrate_difference(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const InVector &fe_function, const Function< spacedim, double > &exact_solution, OutVector &difference, const Quadrature< dim > &q, const NormType &norm, const Function< spacedim, double > *weight=0, const double exponent=2.)