Reference documentation for deal.II version GIT d1e6af55b6 2023-02-07 07:50:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
parsed_convergence_table.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2019 - 2020 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II 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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
18 #include <deal.II/base/patterns.h>
19 #include <deal.II/base/utilities.h>
20 
22 
23 namespace
24 {
25  std::vector<std::string>
26  get_unique_component_names(const std::vector<std::string> &component_names)
27  {
28  auto elements = component_names;
29  auto last = std::unique(elements.begin(), elements.end());
30  elements.resize(last - elements.begin());
31  return elements;
32  }
33 
34 
35 
36  std::vector<ComponentMask>
37  get_unique_component_masks(const std::vector<std::string> &component_names)
38  {
39  const auto unique_component_names =
40  get_unique_component_names(component_names);
41 
42  std::vector<ComponentMask> masks;
43 
44  std::vector<std::vector<bool>> bools(
45  unique_component_names.size(),
46  std::vector<bool>(component_names.size(), false));
47 
48  unsigned int j = 0;
49  for (unsigned int i = 0; i < component_names.size(); ++i)
50  {
51  if (unique_component_names[j] != component_names[i])
52  masks.emplace_back(bools[j++]);
53  bools[j][i] = true;
54  }
55  masks.emplace_back(bools[j++]);
56  AssertDimension(j, unique_component_names.size());
57  return masks;
58  }
59 } // namespace
60 
61 
62 
64  const std::vector<std::string> & solution_names,
65  const std::vector<std::set<VectorTools::NormType>> &list_of_error_norms)
66  : ParsedConvergenceTable(solution_names,
67  list_of_error_norms,
68  2.0,
69  {"cells", "dofs"},
70  "dofs",
71  "reduction_rate_log2",
72  "",
73  3,
74  true)
75 {}
76 
77 
78 
80  const std::vector<std::string> & component_names,
81  const std::vector<std::set<VectorTools::NormType>> &list_of_error_norms,
82  const double exponent,
83  const std::set<std::string> & extra_columns,
84  const std::string & rate_key,
85  const std::string & rate_mode,
86  const std::string & error_file_name,
87  const unsigned int precision,
88  const bool compute_error)
89  : component_names(component_names)
90  , unique_component_names(get_unique_component_names(component_names))
91  , unique_component_masks(get_unique_component_masks(component_names))
92  , norms_per_unique_component(list_of_error_norms)
93  , exponent(exponent)
94  , extra_columns(extra_columns)
95  , rate_key(rate_key)
96  , rate_mode(rate_mode)
97  , precision(precision)
98  , error_file_name(error_file_name)
99  , compute_error(compute_error)
100 {
102  unique_component_names.size());
103 }
104 
105 
106 
107 void
109 {
110  prm.add_parameter("Enable computation of the errors",
112  "When set to false, no computations are performed.");
113 
114  prm.add_parameter("Error precision",
115  precision,
116  "Number of digits to use when printing the error.",
117  Patterns::Integer(0));
118 
119  prm.add_parameter("Error file name",
121  "Set this to a filename with extension .txt, .gpl, .org, "
122  "or .tex to enable writing the convergence table to a "
123  "file.");
124 
125  prm.add_parameter(
126  "List of error norms to compute",
128  "Each component is separated by a semicolon "
129  "and each norm by a comma. See the documentation of VectorTools::NormType "
130  "for a list of implemented norms. If you want to skip a component, leave "
131  "its entry empty.");
132 
133 
134  prm.add_parameter("Exponent for p-norms",
135  exponent,
136  "The exponent to use when computing p-norms.",
137  Patterns::Double(1));
138 
139  prm.add_parameter("Extra columns",
141  "Extra columns to add to the table. Available options "
142  "are dofs and cells.",
143  Patterns::List(Patterns::Selection("dofs|cells")));
144 
145  prm.add_parameter("Rate key",
146  rate_key,
147  "Key to use when computing convergence rates. If "
148  "this is set to a column that is not present, or to the "
149  "empty string, then no error rates are computed.");
150 
151  prm.add_parameter("Rate mode",
152  rate_mode,
153  "What type of error rate to compute. Available options are "
154  "reduction_rate_log2, reduction_rate, and none.",
156  "reduction_rate|reduction_rate_log2|none"));
157 }
158 
159 
160 
161 void
163 {
164  if (compute_error)
165  {
166  // Add convergence rates if the rate_key is not empty
167  if (rate_key != "")
168  {
169  bool has_key = false;
170  for (const auto &col : extra_columns)
171  {
172  if (rate_key == col)
173  has_key = true;
174 
175  if (col != "")
177  }
178 
179  for (const auto &extra_col : extra_column_functions)
180  if (extra_col.second.second == false)
181  {
182  if (rate_key == extra_col.first)
183  has_key = true;
185  extra_col.first);
186  }
187 
188  if (has_key)
189  {
190  if (rate_mode == "reduction_rate_log2")
193  else if (rate_mode == "reduction_rate")
196  else
197  {
198  Assert(rate_mode != "none", ExcInternalError());
199  }
200  }
201  else
202  {
203  AssertThrow(rate_key != "",
204  ExcMessage(
205  "You specified the key <" + rate_key +
206  "> to compute convergence rates, but that key does "
207  "not exist in the current table."));
208  }
209  }
210  }
211 }
212 
213 
214 
215 void
217 {
218  if (compute_error)
219  {
221  table.write_text(out);
222  output_table();
223  }
224 }
225 
226 
227 
228 void
230 {
231  if (compute_error && error_file_name != "")
232  {
234 
235  const std::string error_file_format =
236  error_file_name.substr(error_file_name.find_last_of('.') + 1);
237 
238  std::ofstream table_file(error_file_name);
239 
240  if (error_file_format == "tex")
241  table.write_tex(table_file);
242  else if (error_file_format == "txt")
243  table.write_text(table_file);
244  else if (error_file_format == "gpl")
245  table.write_text(table_file,
247  else if (error_file_format == "org")
249  else
250  {
251  AssertThrow(false,
253  std::string("Unrecognized file format: ") +
254  error_file_format));
255  }
256  table_file.close();
257  }
258 }
259 
260 
261 
262 void
264  const std::string & column_name,
265  const std::function<double()> &custom_function,
266  const bool compute_rate)
267 {
268  extra_column_functions[column_name] = {custom_function, compute_rate};
269 }
270 
void evaluate_all_convergence_rates(const std::string &reference_column_key, const RateMode rate_mode)
void omit_column_from_convergence_rate_evaluation(const std::string &key)
void add_parameter(const std::string &entry, ParameterType &parameter, const std::string &documentation="", const Patterns::PatternBase &pattern= *Patterns::Tools::Convert< ParameterType >::to_pattern(), const bool has_to_be_set=false)
The ParsedConvergenceTable class.
void add_extra_column(const std::string &column_name, const std::function< double()> &custom_function, const bool compute_rate=true)
ParsedConvergenceTable(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}})
void add_parameters(ParameterHandler &prm)
std::set< std::string > extra_columns
const std::vector< std::string > unique_component_names
std::vector< std::set< VectorTools::NormType > > norms_per_unique_component
std::map< std::string, std::pair< std::function< double()>, bool > > extra_column_functions
void write_text(std::ostream &out, const TextOutputFormat format=table_with_headers) const
@ table_with_separate_column_description
void write_tex(std::ostream &file, const bool with_header=true) const
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:461
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:462
static ::ExceptionBase & ExcInternalError()
#define Assert(cond, exc)
Definition: exceptions.h:1583
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1756
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1672