deal.II version 9.8.0
\(\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\}}\)
Loading...
Searching...
No Matches
error_estimator_1d.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2013 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
17
19
22
23#include <deal.II/fe/fe.h>
26#include <deal.II/fe/mapping.h>
27
29
33
41#include <deal.II/lac/vector.h>
42
44
45#include <algorithm>
46#include <cmath>
47#include <complex>
48#include <functional>
49#include <numeric>
50#include <vector>
51
53
54
55template <int spacedim>
56template <typename Number>
57void
60 const DoFHandler<1, spacedim> &dof_handler,
61 const Quadrature<0> &quadrature,
62 const std::map<types::boundary_id, const Function<spacedim, Number> *>
63 &neumann_bc,
64 const ReadVector<Number> &solution,
65 Vector<float> &error,
66 const ComponentMask &component_mask,
67 const Function<spacedim> *coefficients,
68 const unsigned int n_threads,
69 const types::subdomain_id subdomain_id,
70 const types::material_id material_id,
71 const Strategy strategy)
72{
73 // just pass on to the other function
74 std::vector<const ReadVector<Number> *> solutions(1, &solution);
75 std::vector<Vector<float> *> errors(1, &error);
76 ArrayView<Vector<float> *> error_view = make_array_view(errors);
78 dof_handler,
79 quadrature,
80 neumann_bc,
81 make_array_view(solutions),
82 error_view,
83 component_mask,
84 coefficients,
85 n_threads,
86 subdomain_id,
87 material_id,
88 strategy);
89}
90
91
92
93template <int spacedim>
94template <typename Number>
95void
97 const DoFHandler<1, spacedim> &dof_handler,
98 const Quadrature<0> &quadrature,
99 const std::map<types::boundary_id, const Function<spacedim, Number> *>
100 &neumann_bc,
101 const ReadVector<Number> &solution,
102 Vector<float> &error,
103 const ComponentMask &component_mask,
104 const Function<spacedim> *coefficients,
105 const unsigned int n_threads,
106 const types::subdomain_id subdomain_id,
107 const types::material_id material_id,
108 const Strategy strategy)
109{
110 const auto reference_cell = ReferenceCells::Line;
111 estimate(reference_cell.template get_default_linear_mapping<spacedim>(),
112 dof_handler,
113 quadrature,
114 neumann_bc,
115 solution,
116 error,
117 component_mask,
118 coefficients,
119 n_threads,
120 subdomain_id,
121 material_id,
122 strategy);
123}
124
125
126
127template <int spacedim>
128template <typename Number>
129void
131 const DoFHandler<1, spacedim> &dof_handler,
132 const Quadrature<0> &quadrature,
133 const std::map<types::boundary_id, const Function<spacedim, Number> *>
134 &neumann_bc,
135 const ArrayView<const ReadVector<Number> *> &solutions,
136 ArrayView<Vector<float> *> &errors,
137 const ComponentMask &component_mask,
138 const Function<spacedim> *coefficients,
139 const unsigned int n_threads,
140 const types::subdomain_id subdomain_id,
141 const types::material_id material_id,
142 const Strategy strategy)
143{
144 const auto reference_cell = ReferenceCells::Line;
145 estimate(reference_cell.template get_default_linear_mapping<spacedim>(),
146 dof_handler,
147 quadrature,
148 neumann_bc,
149 solutions,
150 errors,
151 component_mask,
152 coefficients,
153 n_threads,
154 subdomain_id,
155 material_id,
156 strategy);
157}
158
159
160
161template <int spacedim>
162template <typename Number>
163void
166 const DoFHandler<1, spacedim> &dof_handler,
167 const hp::QCollection<0> &quadrature,
168 const std::map<types::boundary_id, const Function<spacedim, Number> *>
169 &neumann_bc,
170 const ReadVector<Number> &solution,
171 Vector<float> &error,
172 const ComponentMask &component_mask,
173 const Function<spacedim> *coefficients,
174 const unsigned int n_threads,
175 const types::subdomain_id subdomain_id,
176 const types::material_id material_id,
177 const Strategy strategy)
178{
179 // just pass on to the other function
180 std::vector<const ReadVector<Number> *> solutions(1, &solution);
181 std::vector<Vector<float> *> errors(1, &error);
182 ArrayView<Vector<float> *> error_view = make_array_view(errors);
184 dof_handler,
185 quadrature,
186 neumann_bc,
187 make_array_view(solutions),
188 error_view,
189 component_mask,
190 coefficients,
191 n_threads,
192 subdomain_id,
193 material_id,
194 strategy);
195}
196
197
198
199template <int spacedim>
200template <typename Number>
201void
204 const DoFHandler<1, spacedim> &dof_handler,
205 const hp::QCollection<0> &quadrature,
206 const std::map<types::boundary_id, const Function<spacedim, Number> *>
207 &neumann_bc,
208 const ReadVector<Number> &solution,
209 Vector<float> &error,
210 const ComponentMask &component_mask,
211 const Function<spacedim> *coefficients,
212 const unsigned int n_threads,
213 const types::subdomain_id subdomain_id,
214 const types::material_id material_id,
215 const Strategy strategy)
216{
217 // DEPRECATED
218 // just pass on to the other function
219 std::vector<const ReadVector<Number> *> solutions(1, &solution);
220 std::vector<Vector<float> *> errors(1, &error);
221 ArrayView<Vector<float> *> error_view = make_array_view(errors);
222 const hp::MappingCollection<1, spacedim> mapping_collection(mapping);
223 estimate(mapping_collection,
224 dof_handler,
225 quadrature,
226 neumann_bc,
227 make_array_view(solutions),
228 error_view,
229 component_mask,
230 coefficients,
231 n_threads,
232 subdomain_id,
233 material_id,
234 strategy);
235}
236
237
238
239template <int spacedim>
240template <typename Number>
241void
243 const DoFHandler<1, spacedim> &dof_handler,
244 const hp::QCollection<0> &quadrature,
245 const std::map<types::boundary_id, const Function<spacedim, Number> *>
246 &neumann_bc,
247 const ReadVector<Number> &solution,
248 Vector<float> &error,
249 const ComponentMask &component_mask,
250 const Function<spacedim> *coefficients,
251 const unsigned int n_threads,
252 const types::subdomain_id subdomain_id,
253 const types::material_id material_id,
254 const Strategy strategy)
255{
256 const auto reference_cell = ReferenceCells::Line;
258 reference_cell.template get_default_linear_mapping<spacedim>());
260 dof_handler,
261 quadrature,
262 neumann_bc,
263 solution,
264 error,
265 component_mask,
266 coefficients,
267 n_threads,
268 subdomain_id,
269 material_id,
270 strategy);
271}
272
273
274
275template <int spacedim>
276template <typename Number>
277void
279 const DoFHandler<1, spacedim> &dof_handler,
280 const hp::QCollection<0> &quadrature,
281 const std::map<types::boundary_id, const Function<spacedim, Number> *>
282 &neumann_bc,
283 const ArrayView<const ReadVector<Number> *> &solutions,
284 ArrayView<Vector<float> *> &errors,
285 const ComponentMask &component_mask,
286 const Function<spacedim> *coefficients,
287 const unsigned int n_threads,
288 const types::subdomain_id subdomain_id,
289 const types::material_id material_id,
290 const Strategy strategy)
291{
292 const auto reference_cell = ReferenceCells::Line;
294 reference_cell.template get_default_linear_mapping<spacedim>());
296 dof_handler,
297 quadrature,
298 neumann_bc,
299 solutions,
300 errors,
301 component_mask,
302 coefficients,
303 n_threads,
304 subdomain_id,
305 material_id,
306 strategy);
307}
308
309
310
311template <int spacedim>
312template <typename Number>
313void
316 const DoFHandler<1, spacedim> &dof_handler,
317 const hp::QCollection<0> &,
318 const std::map<types::boundary_id, const Function<spacedim, Number> *>
319 &neumann_bc,
320 const ArrayView<const ReadVector<Number> *> &solutions,
321 ArrayView<Vector<float> *> &errors,
322 const ComponentMask &component_mask,
323 const Function<spacedim> *coefficient,
324 const unsigned int,
325 const types::subdomain_id subdomain_id_,
326 const types::material_id material_id,
327 const Strategy strategy)
328{
330 using number = Number;
332 if (const auto *triangulation = dynamic_cast<
334 &dof_handler.get_triangulation()))
335 {
336 Assert((subdomain_id_ == numbers::invalid_subdomain_id) ||
337 (subdomain_id_ == triangulation->locally_owned_subdomain()),
339 "For distributed Triangulation objects and associated "
340 "DoFHandler objects, asking for any subdomain other than the "
341 "locally owned one does not make sense."));
342 subdomain_id = triangulation->locally_owned_subdomain();
343 }
344 else
345 {
346 subdomain_id = subdomain_id_;
347 }
348
349 const unsigned int n_components = dof_handler.get_fe(0).n_components();
350 const unsigned int n_solution_vectors = solutions.size();
351
352 // sanity checks
354 neumann_bc.end(),
355 ExcMessage("You are not allowed to list the special boundary "
356 "indicator for internal boundaries in your boundary "
357 "value map."));
358
359 for (const auto &boundary_function : neumann_bc)
360 {
361 (void)boundary_function;
362 Assert(boundary_function.second->n_components == n_components,
363 ExcInvalidBoundaryFunction(boundary_function.first,
364 boundary_function.second->n_components,
365 n_components));
366 }
367
368 Assert(component_mask.represents_n_components(n_components),
370 Assert(component_mask.n_selected_components(n_components) > 0,
372
373 Assert((coefficient == nullptr) ||
374 (coefficient->n_components == n_components) ||
375 (coefficient->n_components == 1),
377
378 Assert(solutions.size() > 0, ExcNoSolutions());
379 Assert(solutions.size() == errors.size(),
380 ExcIncompatibleNumberOfElements(solutions.size(), errors.size()));
381 for (unsigned int n = 0; n < solutions.size(); ++n)
382 Assert(solutions[n]->size() == dof_handler.n_dofs(),
383 ExcDimensionMismatch(solutions[n]->size(), dof_handler.n_dofs()));
384
385 Assert((coefficient == nullptr) ||
386 (coefficient->n_components == n_components) ||
387 (coefficient->n_components == 1),
389
390 for (const auto &boundary_function : neumann_bc)
391 {
392 (void)boundary_function;
393 Assert(boundary_function.second->n_components == n_components,
394 ExcInvalidBoundaryFunction(boundary_function.first,
395 boundary_function.second->n_components,
396 n_components));
397 }
398
399 // reserve one slot for each cell and set it to zero
400 for (unsigned int n = 0; n < n_solution_vectors; ++n)
401 (*errors[n]).reinit(dof_handler.get_triangulation().n_active_cells());
402
403 // fields to get the gradients on the present and the neighbor cell.
404 //
405 // for the neighbor gradient, we need several auxiliary fields, depending on
406 // the way we get it (see below)
407 std::vector<std::vector<std::vector<Tensor<1, spacedim, number>>>>
408 gradients_here(n_solution_vectors,
409 std::vector<std::vector<Tensor<1, spacedim, number>>>(
410 2,
411 std::vector<Tensor<1, spacedim, number>>(n_components)));
412 std::vector<std::vector<std::vector<Tensor<1, spacedim, number>>>>
413 gradients_neighbor(gradients_here);
414 std::vector<Vector<typename ProductType<number, double>::type>>
415 grad_dot_n_neighbor(n_solution_vectors,
417 n_components));
418
419 // reserve some space for coefficient values at one point. if there is no
420 // coefficient, then we fill it by unity once and for all and don't set it
421 // any more
422 Vector<double> coefficient_values(n_components);
423 if (coefficient == nullptr)
424 for (unsigned int c = 0; c < n_components; ++c)
425 coefficient_values(c) = 1;
426
427 const QTrapezoid<1> quadrature;
428 const hp::QCollection<1> q_collection(quadrature);
429 const QGauss<0> face_quadrature(1);
430 const hp::QCollection<0> q_face_collection(face_quadrature);
431
432 const hp::FECollection<1, spacedim> &fe = dof_handler.get_fe_collection();
433
434
436 fe,
437 q_collection,
440 /*mapping,*/ fe, q_face_collection, update_normal_vectors);
441
442 // loop over all cells and do something on the cells which we're told to
443 // work on. note that the error indicator is only a sum over the two
444 // contributions from the two vertices of each cell.
445 for (const auto &cell : dof_handler.active_cell_iterators())
446 if (((subdomain_id == numbers::invalid_subdomain_id) ||
447 (cell->subdomain_id() == subdomain_id)) &&
448 ((material_id == numbers::invalid_material_id) ||
449 (cell->material_id() == material_id)))
450 {
451 for (unsigned int n = 0; n < n_solution_vectors; ++n)
452 (*errors[n])(cell->active_cell_index()) = 0;
453
454 fe_values.reinit(cell);
455 for (unsigned int s = 0; s < n_solution_vectors; ++s)
456 fe_values.get_present_fe_values().get_function_gradients(
457 *solutions[s], gradients_here[s]);
458
459 // loop over the two points bounding this line. n==0 is left point,
460 // n==1 is right point
461 for (unsigned int n = 0; n < 2; ++n)
462 {
463 // find left or right active neighbor
464 auto neighbor = cell->neighbor(n);
465 if (neighbor.state() == IteratorState::valid)
466 while (neighbor->has_children())
467 neighbor = neighbor->child(n == 0 ? 1 : 0);
468
469 fe_face_values.reinit(cell, n);
470 Tensor<1, spacedim> normal =
471 fe_face_values.get_present_fe_values().get_normal_vectors()[0];
472
473 if (neighbor.state() == IteratorState::valid)
474 {
475 fe_values.reinit(neighbor);
476
477 for (unsigned int s = 0; s < n_solution_vectors; ++s)
478 fe_values.get_present_fe_values().get_function_gradients(
479 *solutions[s], gradients_neighbor[s]);
480
481 fe_face_values.reinit(neighbor, n == 0 ? 1 : 0);
482 Tensor<1, spacedim> neighbor_normal =
483 fe_face_values.get_present_fe_values()
484 .get_normal_vectors()[0];
485
486 // extract the gradient in normal direction of all the
487 // components.
488 for (unsigned int s = 0; s < n_solution_vectors; ++s)
489 for (unsigned int c = 0; c < n_components; ++c)
490 grad_dot_n_neighbor[s](c) =
491 -(gradients_neighbor[s][n == 0 ? 1 : 0][c] *
492 neighbor_normal);
493 }
494 else if (neumann_bc.find(n) != neumann_bc.end())
495 // if Neumann b.c., then fill the gradients field which will be
496 // used later on.
497 {
498 if (n_components == 1)
499 {
500 const Number v =
501 neumann_bc.find(n)->second->value(cell->vertex(n));
502
503 for (unsigned int s = 0; s < n_solution_vectors; ++s)
504 grad_dot_n_neighbor[s](0) = v;
505 }
506 else
507 {
508 Vector<Number> v(n_components);
509 neumann_bc.find(n)->second->vector_value(cell->vertex(n),
510 v);
511
512 for (unsigned int s = 0; s < n_solution_vectors; ++s)
513 grad_dot_n_neighbor[s] = v;
514 }
515 }
516 else
517 // fill with zeroes.
518 for (unsigned int s = 0; s < n_solution_vectors; ++s)
519 grad_dot_n_neighbor[s] = 0;
520
521 // if there is a coefficient, then evaluate it at the present
522 // position. if there is none, reuse the preset values.
523 if (coefficient != nullptr)
524 {
525 if (coefficient->n_components == 1)
526 {
527 const double c_value = coefficient->value(cell->vertex(n));
528 for (unsigned int c = 0; c < n_components; ++c)
529 coefficient_values(c) = c_value;
530 }
531 else
532 coefficient->vector_value(cell->vertex(n),
533 coefficient_values);
534 }
535
536
537 for (unsigned int s = 0; s < n_solution_vectors; ++s)
538 for (unsigned int component = 0; component < n_components;
539 ++component)
540 if (component_mask[component] == true)
541 {
542 // get gradient here
544 grad_dot_n_here =
545 gradients_here[s][n][component] * normal;
546
547 const typename ProductType<number, double>::type jump =
548 ((grad_dot_n_here - grad_dot_n_neighbor[s](component)) *
549 coefficient_values(component));
550 (*errors[s])(cell->active_cell_index()) +=
552 typename ProductType<number,
553 double>::type>::abs_square(jump) *
554 cell->diameter();
555 }
556 }
557
558 for (unsigned int s = 0; s < n_solution_vectors; ++s)
559 (*errors[s])(cell->active_cell_index()) =
560 std::sqrt((*errors[s])(cell->active_cell_index()));
561 }
562}
563
564
565
566template <int spacedim>
567template <typename Number>
568void
571 const DoFHandler<1, spacedim> &dof_handler,
572 const hp::QCollection<0> &quadrature,
573 const std::map<types::boundary_id, const Function<spacedim, Number> *>
574 &neumann_bc,
575 const ArrayView<const ReadVector<Number> *> &solutions,
576 ArrayView<Vector<float> *> &errors,
577 const ComponentMask &component_mask,
578 const Function<spacedim> *coefficients,
579 const unsigned int n_threads,
580 const types::subdomain_id subdomain_id,
581 const types::material_id material_id,
582 const Strategy strategy)
583{
584 // DEPRECATED
585 // just pass on to the other function
586 const hp::MappingCollection<1, spacedim> mapping_collection(mapping);
587 estimate(mapping_collection,
588 dof_handler,
589 quadrature,
590 neumann_bc,
591 solutions,
592 errors,
593 component_mask,
594 coefficients,
595 n_threads,
596 subdomain_id,
597 material_id,
598 strategy);
599}
600
601
602
603template <int spacedim>
604template <typename Number>
605void
608 const DoFHandler<1, spacedim> &dof_handler,
609 const Quadrature<0> &quadrature,
610 const std::map<types::boundary_id, const Function<spacedim, Number> *>
611 &neumann_bc,
612 const ArrayView<const ReadVector<Number> *> &solutions,
613 ArrayView<Vector<float> *> &errors,
614 const ComponentMask &component_mask,
615 const Function<spacedim> *coefficients,
616 const unsigned int n_threads,
617 const types::subdomain_id subdomain_id,
618 const types::material_id material_id,
619 const Strategy strategy)
620{
621 const hp::MappingCollection<1, spacedim> mapping_collection(mapping);
622 const hp::QCollection<0> quadrature_collection(quadrature);
623 estimate(mapping_collection,
624 dof_handler,
625 quadrature_collection,
626 neumann_bc,
627 solutions,
628 errors,
629 component_mask,
630 coefficients,
631 n_threads,
632 subdomain_id,
633 material_id,
634 strategy);
635}
636
637
638
639// explicit instantiations
640#include "numerics/error_estimator_1d.inst"
641
642
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
bool represents_n_components(const unsigned int n) const
unsigned int n_selected_components(const unsigned int overall_number_of_components=numbers::invalid_unsigned_int) const
const hp::FECollection< dim, spacedim > & get_fe_collection() const
const FiniteElement< dim, spacedim > & get_fe(const types::fe_index index=0) const
const Triangulation< dim, spacedim > & get_triangulation() const
types::global_dof_index n_dofs() const
unsigned int n_components() const
const unsigned int n_components
Definition function.h:162
virtual RangeNumberType value(const Point< dim > &p, const unsigned int component=0) const
virtual void vector_value(const Point< dim > &p, Vector< RangeNumberType > &values) const
@ cell_diameter_over_24
Kelly error estimator with the factor .
static void estimate(const Mapping< 1, spacedim > &mapping, const DoFHandler< 1, spacedim > &dof, const Quadrature< 0 > &quadrature, const std::map< types::boundary_id, const Function< spacedim, Number > * > &neumann_bc, const ReadVector< Number > &solution, Vector< float > &error, const ComponentMask &component_mask={}, const Function< spacedim > *coefficient=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)
static void estimate(const Mapping< dim, spacedim > &mapping, const DoFHandler< dim, spacedim > &dof, const Quadrature< dim - 1 > &quadrature, const std::map< types::boundary_id, const Function< spacedim, Number > * > &neumann_bc, const ReadVector< Number > &solution, Vector< float > &error, const ComponentMask &component_mask={}, 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)
Abstract base class for mapping classes.
Definition mapping.h:318
unsigned int n_active_cells() const
const FEValuesType & get_present_fe_values() const
Definition fe_values.h:693
void reinit(const TriaIterator< DoFCellAccessor< dim, spacedim, 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:294
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
IteratorRange< active_cell_iterator > active_cell_iterators() const
static ::ExceptionBase & ExcInvalidBoundaryFunction(types::boundary_id arg1, int arg2, int arg3)
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcNoSolutions()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcInvalidCoefficient()
static ::ExceptionBase & ExcIncompatibleNumberOfElements(int arg1, int arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcInvalidComponentMask()
#define AssertThrow(cond, exc)
@ update_normal_vectors
Normal vectors.
@ update_gradients
Shape function gradients.
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:314
MappingQ< dim, spacedim > StaticMappingQ1< dim, spacedim >::mapping
Definition mapping_q1.h:101
@ valid
Iterator points to a valid object.
constexpr ReferenceCell< 1 > Line
constexpr types::boundary_id internal_face_boundary_id
Definition types.h:327
constexpr types::material_id invalid_material_id
Definition types.h:292
constexpr types::subdomain_id invalid_subdomain_id
Definition types.h:393
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
unsigned int material_id
Definition types.h:182
unsigned int boundary_id
Definition types.h:159
unsigned int subdomain_id
Definition types.h:50
*  *  FEFaceValues< 2 > fe_face_values(fe, face_quadrature_formula, update_values|update_quadrature_points| *  update_normal_vectors|update_JxW_values)
typename internal::ProductTypeImpl< std::decay_t< T >, std::decay_t< U > >::type type