Reference documentation for deal.II version 9.0.0
error_estimator_1d.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2018 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/thread_management.h>
17 #include <deal.II/base/quadrature.h>
18 #include <deal.II/base/quadrature_lib.h>
19 #include <deal.II/base/work_stream.h>
20 #include <deal.II/lac/vector.h>
21 #include <deal.II/lac/la_vector.h>
22 #include <deal.II/lac/la_parallel_vector.h>
23 #include <deal.II/lac/block_vector.h>
24 #include <deal.II/lac/la_parallel_block_vector.h>
25 #include <deal.II/lac/petsc_parallel_vector.h>
26 #include <deal.II/lac/petsc_parallel_block_vector.h>
27 #include <deal.II/lac/trilinos_vector.h>
28 #include <deal.II/lac/trilinos_parallel_block_vector.h>
29 #include <deal.II/grid/tria_iterator.h>
30 #include <deal.II/base/geometry_info.h>
31 #include <deal.II/dofs/dof_handler.h>
32 #include <deal.II/dofs/dof_accessor.h>
33 #include <deal.II/fe/fe.h>
34 #include <deal.II/fe/fe_values.h>
35 #include <deal.II/hp/fe_values.h>
36 #include <deal.II/fe/fe_update_flags.h>
37 #include <deal.II/fe/mapping_q1.h>
38 #include <deal.II/hp/q_collection.h>
39 #include <deal.II/hp/mapping_collection.h>
40 #include <deal.II/numerics/error_estimator.h>
41 #include <deal.II/distributed/tria.h>
42 
43 
44 #include <numeric>
45 #include <algorithm>
46 #include <cmath>
47 #include <vector>
48 #include <functional>
49 
50 DEAL_II_NAMESPACE_OPEN
51 
52 
53 
54 template <int spacedim>
55 template <typename InputVector, typename DoFHandlerType>
56 void
58 estimate (const Mapping<1,spacedim> &mapping,
59  const DoFHandlerType &dof_handler,
60  const Quadrature<0> &quadrature,
62  const InputVector &solution,
63  Vector<float> &error,
64  const ComponentMask &component_mask,
65  const Function<spacedim> *coefficients,
66  const unsigned int n_threads,
67  const types::subdomain_id subdomain_id,
68  const types::material_id material_id,
69  const Strategy strategy)
70 {
71  // just pass on to the other function
72  const std::vector<const InputVector *> solutions (1, &solution);
73  std::vector<Vector<float>*> errors (1, &error);
74  estimate (mapping, dof_handler, quadrature, neumann_bc, solutions, errors,
75  component_mask, coefficients, n_threads, subdomain_id, material_id,strategy);
76 }
77 
78 
79 
80 template <int spacedim>
81 template <typename InputVector, typename DoFHandlerType>
82 void
84 estimate (const DoFHandlerType &dof_handler,
85  const Quadrature<0> &quadrature,
87  const InputVector &solution,
88  Vector<float> &error,
89  const ComponentMask &component_mask,
90  const Function<spacedim> *coefficients,
91  const unsigned int n_threads,
92  const types::subdomain_id subdomain_id,
93  const types::material_id material_id,
94  const Strategy strategy)
95 {
96  estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solution,
97  error, component_mask, coefficients, n_threads, subdomain_id, material_id,strategy);
98 }
99 
100 
101 
102 template <int spacedim>
103 template <typename InputVector, typename DoFHandlerType>
104 void
106 estimate (const DoFHandlerType &dof_handler,
107  const Quadrature<0> &quadrature,
109  const std::vector<const InputVector *> &solutions,
110  std::vector<Vector<float>*> &errors,
111  const ComponentMask &component_mask,
112  const Function<spacedim> *coefficients,
113  const unsigned int n_threads,
114  const types::subdomain_id subdomain_id,
115  const types::material_id material_id,
116  const Strategy strategy)
117 {
118  estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solutions,
119  errors, component_mask, coefficients, n_threads, subdomain_id, material_id,strategy);
120 }
121 
122 
123 
124 template <int spacedim>
125 template <typename InputVector, typename DoFHandlerType>
126 void
129  const DoFHandlerType &dof_handler,
130  const hp::QCollection<0> &quadrature,
132  const InputVector &solution,
133  Vector<float> &error,
134  const ComponentMask &component_mask,
135  const Function<spacedim> *coefficients,
136  const unsigned int n_threads,
137  const types::subdomain_id subdomain_id,
138  const types::material_id material_id,
139  const Strategy strategy)
140 {
141  // just pass on to the other function
142  const std::vector<const InputVector *> solutions (1, &solution);
143  std::vector<Vector<float>*> errors (1, &error);
144  estimate (mapping, dof_handler, quadrature, neumann_bc, solutions, errors,
145  component_mask, coefficients, n_threads, subdomain_id, material_id, strategy);
146 }
147 
148 
149 template <int spacedim>
150 template <typename InputVector, typename DoFHandlerType>
151 void
153 estimate (const DoFHandlerType &dof_handler,
154  const hp::QCollection<0> &quadrature,
156  const InputVector &solution,
157  Vector<float> &error,
158  const ComponentMask &component_mask,
159  const Function<spacedim> *coefficients,
160  const unsigned int n_threads,
161  const types::subdomain_id subdomain_id,
162  const types::material_id material_id,
163  const Strategy strategy)
164 {
165  estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solution,
166  error, component_mask, coefficients, n_threads, subdomain_id, material_id,strategy);
167 }
168 
169 
170 
171 template <int spacedim>
172 template <typename InputVector, typename DoFHandlerType>
173 void
175 estimate (const DoFHandlerType &dof_handler,
176  const hp::QCollection<0> &quadrature,
178  const std::vector<const InputVector *> &solutions,
179  std::vector<Vector<float>*> &errors,
180  const ComponentMask &component_mask,
181  const Function<spacedim> *coefficients,
182  const unsigned int n_threads,
183  const types::subdomain_id subdomain_id,
184  const types::material_id material_id,
185  const Strategy strategy)
186 {
187  estimate(StaticMappingQ1<1,spacedim>::mapping, dof_handler, quadrature, neumann_bc, solutions,
188  errors, component_mask, coefficients, n_threads, subdomain_id, material_id,strategy);
189 }
190 
191 
192 
193 
194 template <int spacedim>
195 template <typename InputVector, typename DoFHandlerType>
197 estimate (const Mapping<1,spacedim> & /*mapping*/,
198  const DoFHandlerType & /*dof_handler*/,
199  const hp::QCollection<0> &,
200  const typename FunctionMap<spacedim,typename InputVector::value_type>::type & /*neumann_bc*/,
201  const std::vector<const InputVector *> & /*solutions*/,
202  std::vector<Vector<float>*> & /*errors*/,
203  const ComponentMask & /*component_mask_*/,
204  const Function<spacedim> * /*coefficient*/,
205  const unsigned int,
206  const types::subdomain_id /*subdomain_id*/,
207  const types::material_id /*material_id*/,
208  const Strategy /*strategy*/)
209 {
210  Assert (false, ExcInternalError());
211 }
212 
213 
214 
215 template <int spacedim>
216 template <typename InputVector, typename DoFHandlerType>
219  const DoFHandlerType &dof_handler,
220  const Quadrature<0> &,
222  const std::vector<const InputVector *> &solutions,
223  std::vector<Vector<float>*> &errors,
224  const ComponentMask &component_mask,
225  const Function<spacedim> *coefficient,
226  const unsigned int,
227  const types::subdomain_id subdomain_id_,
228  const types::material_id material_id,
229  const Strategy strategy)
230 {
232  typedef typename InputVector::value_type number;
233 #ifdef DEAL_II_WITH_P4EST
234  if (dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>*>
235  (&dof_handler.get_triangulation())
236  != nullptr)
237  Assert ((subdomain_id_ == numbers::invalid_subdomain_id)
238  ||
239  (subdomain_id_ ==
241  (dof_handler.get_triangulation()).locally_owned_subdomain()),
242  ExcMessage ("For parallel distributed triangulations, the only "
243  "valid subdomain_id that can be passed here is the "
244  "one that corresponds to the locally owned subdomain id."));
245 
246  const types::subdomain_id subdomain_id
247  = ((dynamic_cast<const parallel::distributed::Triangulation<1,spacedim>*>
248  (&dof_handler.get_triangulation())
249  != nullptr)
250  ?
252  (dof_handler.get_triangulation()).locally_owned_subdomain()
253  :
254  subdomain_id_);
255 #else
256  const types::subdomain_id subdomain_id
257  = subdomain_id_;
258 #endif
259 
260  const unsigned int n_components = dof_handler.get_fe(0).n_components();
261  const unsigned int n_solution_vectors = solutions.size();
262 
263  // sanity checks
264  Assert (neumann_bc.find(numbers::internal_face_boundary_id) == neumann_bc.end(),
265  ExcMessage("You are not allowed to list the special boundary "
266  "indicator for internal boundaries in your boundary "
267  "value map."));
268 
270  i!=neumann_bc.end(); ++i)
271  Assert (i->second->n_components == n_components,
273  i->second->n_components,
274  n_components));
275 
276  Assert (component_mask.represents_n_components(n_components),
278  Assert (component_mask.n_selected_components(n_components) > 0,
280 
281  Assert ((coefficient == nullptr) ||
282  (coefficient->n_components == n_components) ||
283  (coefficient->n_components == 1),
285 
286  Assert (solutions.size() > 0,
287  ExcNoSolutions());
288  Assert (solutions.size() == errors.size(),
289  ExcIncompatibleNumberOfElements(solutions.size(), errors.size()));
290  for (unsigned int n=0; n<solutions.size(); ++n)
291  Assert (solutions[n]->size() == dof_handler.n_dofs(),
292  ExcDimensionMismatch(solutions[n]->size(),
293  dof_handler.n_dofs()));
294 
295  Assert ((coefficient == nullptr) ||
296  (coefficient->n_components == n_components) ||
297  (coefficient->n_components == 1),
299 
301  i!=neumann_bc.end(); ++i)
302  Assert (i->second->n_components == n_components,
304  i->second->n_components,
305  n_components));
306 
307  // reserve one slot for each cell and set it to zero
308  for (unsigned int n=0; n<n_solution_vectors; ++n)
309  (*errors[n]).reinit (dof_handler.get_triangulation().n_active_cells());
310 
311  // fields to get the gradients on the present and the neighbor cell.
312  //
313  // for the neighbor gradient, we need several auxiliary fields, depending on
314  // the way we get it (see below)
315  std::vector<std::vector<std::vector<Tensor<1,spacedim,number> > > >
316  gradients_here (n_solution_vectors,
317  std::vector<std::vector<Tensor<1,spacedim,number> > >(2, std::vector<Tensor<1,spacedim,number> >(n_components)));
318  std::vector<std::vector<std::vector<Tensor<1,spacedim,number> > > >
319  gradients_neighbor (gradients_here);
320  std::vector<Vector<typename ProductType<number,double>::type> >
321  grad_dot_n_neighbor (n_solution_vectors, Vector<typename ProductType<number,double>::type>(n_components));
322 
323  // reserve some space for coefficient values at one point. if there is no
324  // coefficient, then we fill it by unity once and for all and don't set it
325  // any more
326  Vector<double> coefficient_values (n_components);
327  if (coefficient == nullptr)
328  for (unsigned int c=0; c<n_components; ++c)
329  coefficient_values(c) = 1;
330 
331  const QTrapez<1> quadrature;
332  const hp::QCollection<1> q_collection(quadrature);
333  const QGauss<0> face_quadrature(1);
334  const hp::QCollection<0> q_face_collection(face_quadrature);
335 
336  const hp::FECollection<1,spacedim> &fe = dof_handler.get_fe_collection();
337 
338  hp::MappingCollection<1,spacedim> mapping_collection;
339  mapping_collection.push_back (mapping);
340 
341  hp::FEValues<1,spacedim> fe_values (mapping_collection, fe, q_collection,
343  hp::FEFaceValues<1,spacedim> fe_face_values (/*mapping_collection,*/ fe, q_face_collection,
345 
346  // loop over all cells and do something on the cells which we're told to
347  // work on. note that the error indicator is only a sum over the two
348  // contributions from the two vertices of each cell.
349  for (typename DoFHandlerType::active_cell_iterator cell = dof_handler.begin_active();
350  cell != dof_handler.end();
351  ++cell)
352  if (((subdomain_id == numbers::invalid_subdomain_id)
353  ||
354  (cell->subdomain_id() == subdomain_id))
355  &&
356  ((material_id == numbers::invalid_material_id)
357  ||
358  (cell->material_id() == material_id)))
359  {
360  for (unsigned int n=0; n<n_solution_vectors; ++n)
361  (*errors[n])(cell->active_cell_index()) = 0;
362 
363  fe_values.reinit (cell);
364  for (unsigned int s=0; s<n_solution_vectors; ++s)
365  fe_values.get_present_fe_values()
366  .get_function_gradients (*solutions[s], gradients_here[s]);
367 
368  // loop over the two points bounding this line. n==0 is left point,
369  // n==1 is right point
370  for (unsigned int n=0; n<2; ++n)
371  {
372  // find left or right active neighbor
373  typename DoFHandlerType::cell_iterator neighbor = cell->neighbor(n);
374  if (neighbor.state() == IteratorState::valid)
375  while (neighbor->has_children())
376  neighbor = neighbor->child(n==0 ? 1 : 0);
377 
378  fe_face_values.reinit (cell, n);
379  Tensor<1,spacedim> normal =
380  fe_face_values.get_present_fe_values().get_all_normal_vectors()[0];
381 
382  if (neighbor.state() == IteratorState::valid)
383  {
384  fe_values.reinit (neighbor);
385 
386  for (unsigned int s=0; s<n_solution_vectors; ++s)
387  fe_values.get_present_fe_values()
388  .get_function_gradients (*solutions[s],
389  gradients_neighbor[s]);
390 
391  fe_face_values.reinit (neighbor, n==0 ? 1 : 0);
392  Tensor<1,spacedim> neighbor_normal =
393  fe_face_values.get_present_fe_values().get_all_normal_vectors()[0];
394 
395  // extract the gradient in normal direction of all the components.
396  for (unsigned int s=0; s<n_solution_vectors; ++s)
397  for (unsigned int c=0; c<n_components; ++c)
398  grad_dot_n_neighbor[s](c)
399  = - (gradients_neighbor[s][n==0 ? 1 : 0][c]*neighbor_normal);
400  }
401  else if (neumann_bc.find(n) != neumann_bc.end())
402  // if Neumann b.c., then fill the gradients field which will be
403  // used later on.
404  {
405  if (n_components==1)
406  {
407  const typename InputVector::value_type
408  v = neumann_bc.find(n)->second->value(cell->vertex(n));
409 
410  for (unsigned int s=0; s<n_solution_vectors; ++s)
411  grad_dot_n_neighbor[s](0) = v;
412  }
413  else
414  {
415  Vector<typename InputVector::value_type> v(n_components);
416  neumann_bc.find(n)->second->vector_value(cell->vertex(n), v);
417 
418  for (unsigned int s=0; s<n_solution_vectors; ++s)
419  grad_dot_n_neighbor[s] = v;
420  }
421  }
422  else
423  // fill with zeroes.
424  for (unsigned int s=0; s<n_solution_vectors; ++s)
425  grad_dot_n_neighbor[s] = 0;
426 
427  // if there is a coefficient, then evaluate it at the present
428  // position. if there is none, reuse the preset values.
429  if (coefficient != nullptr)
430  {
431  if (coefficient->n_components == 1)
432  {
433  const double c_value = coefficient->value (cell->vertex(n));
434  for (unsigned int c=0; c<n_components; ++c)
435  coefficient_values(c) = c_value;
436  }
437  else
438  coefficient->vector_value(cell->vertex(n),
439  coefficient_values);
440  }
441 
442 
443  for (unsigned int s=0; s<n_solution_vectors; ++s)
444  for (unsigned int component=0; component<n_components; ++component)
445  if (component_mask[component] == true)
446  {
447  // get gradient here
448  const typename ProductType<number,double>::type
449  grad_dot_n_here = gradients_here[s][n][component] * normal;
450 
451  const typename ProductType<number,double>::type
452  jump = ((grad_dot_n_here - grad_dot_n_neighbor[s](component)) *
453  coefficient_values(component));
454  (*errors[s])(cell->active_cell_index())
455  += numbers::NumberTraits<typename ProductType<number,double>::type>::abs_square(jump) * cell->diameter();
456  }
457  }
458 
459  for (unsigned int s=0; s<n_solution_vectors; ++s)
460  (*errors[s])(cell->active_cell_index()) = std::sqrt((*errors[s])(cell->active_cell_index()));
461  }
462 }
463 
464 
465 // explicit instantiations
466 #include "error_estimator_1d.inst"
467 
468 
469 DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcInvalidBoundaryFunction(types::boundary_id arg1, int arg2, int arg3)
static ::ExceptionBase & ExcInvalidCoefficient()
const types::subdomain_id invalid_subdomain_id
Definition: types.h:248
const unsigned int n_components
Definition: function.h:154
static ::ExceptionBase & ExcInvalidComponentMask()
void push_back(const Mapping< dim, spacedim > &new_mapping)
bool represents_n_components(const unsigned int n) const
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
unsigned int material_id
Definition: types.h:133
const ::FEValues< dim, spacedim > & get_present_fe_values() const
Definition: fe_values.h:598
void reinit(const TriaIterator< DoFCellAccessor< DoFHandlerType, lda > > cell, const unsigned int q_index=numbers::invalid_unsigned_int, const unsigned int mapping_index=numbers::invalid_unsigned_int, const unsigned int fe_index=numbers::invalid_unsigned_int)
Definition: fe_values.cc:144
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1142
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
Abstract base class for mapping classes.
Definition: dof_tools.h:46
static void estimate(const Mapping< dim, spacedim > &mapping, const DoFHandlerType &dof, const Quadrature< dim-1 > &quadrature, const typename FunctionMap< spacedim, typename InputVector::value_type >::type &neumann_bc, const InputVector &solution, Vector< float > &error, const ComponentMask &component_mask=ComponentMask(), const Function< spacedim > *coefficients=nullptr, const unsigned int n_threads=numbers::invalid_unsigned_int, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id, const types::material_id material_id=numbers::invalid_material_id, const Strategy strategy=cell_diameter_over_24)
std::map< types::boundary_id, const Function< dim, Number > * > type
Definition: function_map.h:81
static ::ExceptionBase & ExcIncompatibleNumberOfElements(int arg1, int arg2)
virtual void vector_value(const Point< dim > &p, Vector< RangeNumberType > &values) const
unsigned int subdomain_id
Definition: types.h:42
void reinit(const TriaIterator< DoFCellAccessor< DoFHandlerType, lda > > cell, const unsigned int face_no, const unsigned int q_index=numbers::invalid_unsigned_int, const unsigned int mapping_index=numbers::invalid_unsigned_int, const unsigned int fe_index=numbers::invalid_unsigned_int)
Definition: fe_values.cc:261
Definition: mpi.h:53
Shape function gradients.
Normal vectors.
unsigned int n_selected_components(const unsigned int overall_number_of_components=numbers::invalid_unsigned_int) const
static ::ExceptionBase & ExcNotImplemented()
Iterator points to a valid object.
const types::boundary_id internal_face_boundary_id
Definition: types.h:219
virtual RangeNumberType value(const Point< dim > &p, const unsigned int component=0) const
Kelly error estimator with the factor .
const types::material_id invalid_material_id
Definition: types.h:194
static ::ExceptionBase & ExcNoSolutions()
static ::ExceptionBase & ExcInternalError()