deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00:01+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\}}\)
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
59 const Mapping<1, spacedim> &mapping,
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);
77 estimate(mapping,
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);
183 estimate(mapping,
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
203 const DoFHandler<1, spacedim> &dof_handler,
204 const hp::QCollection<0> &quadrature,
205 const std::map<types::boundary_id, const Function<spacedim, Number> *>
206 &neumann_bc,
207 const ReadVector<Number> &solution,
208 Vector<float> &error,
209 const ComponentMask &component_mask,
210 const Function<spacedim> *coefficients,
211 const unsigned int n_threads,
212 const types::subdomain_id subdomain_id,
213 const types::material_id material_id,
214 const Strategy strategy)
215{
216 const auto reference_cell = ReferenceCells::Line;
218 reference_cell.template get_default_linear_mapping<spacedim>());
219 estimate(mapping,
220 dof_handler,
221 quadrature,
222 neumann_bc,
223 solution,
224 error,
225 component_mask,
226 coefficients,
227 n_threads,
228 subdomain_id,
229 material_id,
230 strategy);
231}
232
233
234
235template <int spacedim>
236template <typename Number>
237void
239 const DoFHandler<1, spacedim> &dof_handler,
240 const hp::QCollection<0> &quadrature,
241 const std::map<types::boundary_id, const Function<spacedim, Number> *>
242 &neumann_bc,
243 const ArrayView<const ReadVector<Number> *> &solutions,
244 ArrayView<Vector<float> *> &errors,
245 const ComponentMask &component_mask,
246 const Function<spacedim> *coefficients,
247 const unsigned int n_threads,
248 const types::subdomain_id subdomain_id,
249 const types::material_id material_id,
250 const Strategy strategy)
251{
252 const auto reference_cell = ReferenceCells::Line;
254 reference_cell.template get_default_linear_mapping<spacedim>());
255 estimate(mapping,
256 dof_handler,
257 quadrature,
258 neumann_bc,
259 solutions,
260 errors,
261 component_mask,
262 coefficients,
263 n_threads,
264 subdomain_id,
265 material_id,
266 strategy);
267}
268
269
270
271template <int spacedim>
272template <typename Number>
273void
276 const DoFHandler<1, spacedim> &dof_handler,
277 const hp::QCollection<0> &,
278 const std::map<types::boundary_id, const Function<spacedim, Number> *>
279 &neumann_bc,
280 const ArrayView<const ReadVector<Number> *> &solutions,
281 ArrayView<Vector<float> *> &errors,
282 const ComponentMask &component_mask,
283 const Function<spacedim> *coefficient,
284 const unsigned int,
285 const types::subdomain_id subdomain_id_,
286 const types::material_id material_id,
287 const Strategy strategy)
288{
289 AssertThrow(strategy == cell_diameter_over_24, ExcNotImplemented());
290 using number = Number;
292 if (const auto *triangulation = dynamic_cast<
294 &dof_handler.get_triangulation()))
295 {
296 Assert((subdomain_id_ == numbers::invalid_subdomain_id) ||
297 (subdomain_id_ == triangulation->locally_owned_subdomain()),
299 "For distributed Triangulation objects and associated "
300 "DoFHandler objects, asking for any subdomain other than the "
301 "locally owned one does not make sense."));
302 subdomain_id = triangulation->locally_owned_subdomain();
303 }
304 else
305 {
306 subdomain_id = subdomain_id_;
307 }
308
309 const unsigned int n_components = dof_handler.get_fe(0).n_components();
310 const unsigned int n_solution_vectors = solutions.size();
311
312 // sanity checks
314 neumann_bc.end(),
315 ExcMessage("You are not allowed to list the special boundary "
316 "indicator for internal boundaries in your boundary "
317 "value map."));
318
319 for (const auto &boundary_function : neumann_bc)
320 {
321 (void)boundary_function;
322 Assert(boundary_function.second->n_components == n_components,
323 ExcInvalidBoundaryFunction(boundary_function.first,
324 boundary_function.second->n_components,
325 n_components));
326 }
327
328 Assert(component_mask.represents_n_components(n_components),
329 ExcInvalidComponentMask());
330 Assert(component_mask.n_selected_components(n_components) > 0,
331 ExcInvalidComponentMask());
332
333 Assert((coefficient == nullptr) ||
334 (coefficient->n_components == n_components) ||
335 (coefficient->n_components == 1),
336 ExcInvalidCoefficient());
337
338 Assert(solutions.size() > 0, ExcNoSolutions());
339 Assert(solutions.size() == errors.size(),
340 ExcIncompatibleNumberOfElements(solutions.size(), errors.size()));
341 for (unsigned int n = 0; n < solutions.size(); ++n)
342 Assert(solutions[n]->size() == dof_handler.n_dofs(),
343 ExcDimensionMismatch(solutions[n]->size(), dof_handler.n_dofs()));
344
345 Assert((coefficient == nullptr) ||
346 (coefficient->n_components == n_components) ||
347 (coefficient->n_components == 1),
348 ExcInvalidCoefficient());
349
350 for (const auto &boundary_function : neumann_bc)
351 {
352 (void)boundary_function;
353 Assert(boundary_function.second->n_components == n_components,
354 ExcInvalidBoundaryFunction(boundary_function.first,
355 boundary_function.second->n_components,
356 n_components));
357 }
358
359 // reserve one slot for each cell and set it to zero
360 for (unsigned int n = 0; n < n_solution_vectors; ++n)
361 (*errors[n]).reinit(dof_handler.get_triangulation().n_active_cells());
362
363 // fields to get the gradients on the present and the neighbor cell.
364 //
365 // for the neighbor gradient, we need several auxiliary fields, depending on
366 // the way we get it (see below)
367 std::vector<std::vector<std::vector<Tensor<1, spacedim, number>>>>
368 gradients_here(n_solution_vectors,
369 std::vector<std::vector<Tensor<1, spacedim, number>>>(
370 2,
371 std::vector<Tensor<1, spacedim, number>>(n_components)));
372 std::vector<std::vector<std::vector<Tensor<1, spacedim, number>>>>
373 gradients_neighbor(gradients_here);
374 std::vector<Vector<typename ProductType<number, double>::type>>
375 grad_dot_n_neighbor(n_solution_vectors,
377 n_components));
378
379 // reserve some space for coefficient values at one point. if there is no
380 // coefficient, then we fill it by unity once and for all and don't set it
381 // any more
382 Vector<double> coefficient_values(n_components);
383 if (coefficient == nullptr)
384 for (unsigned int c = 0; c < n_components; ++c)
385 coefficient_values(c) = 1;
386
387 const QTrapezoid<1> quadrature;
388 const hp::QCollection<1> q_collection(quadrature);
389 const QGauss<0> face_quadrature(1);
390 const hp::QCollection<0> q_face_collection(face_quadrature);
391
392 const hp::FECollection<1, spacedim> &fe = dof_handler.get_fe_collection();
393
394
395 hp::FEValues<1, spacedim> fe_values(mapping,
396 fe,
397 q_collection,
399 hp::FEFaceValues<1, spacedim> fe_face_values(
400 /*mapping,*/ fe, q_face_collection, update_normal_vectors);
401
402 // loop over all cells and do something on the cells which we're told to
403 // work on. note that the error indicator is only a sum over the two
404 // contributions from the two vertices of each cell.
405 for (const auto &cell : dof_handler.active_cell_iterators())
406 if (((subdomain_id == numbers::invalid_subdomain_id) ||
407 (cell->subdomain_id() == subdomain_id)) &&
408 ((material_id == numbers::invalid_material_id) ||
409 (cell->material_id() == material_id)))
410 {
411 for (unsigned int n = 0; n < n_solution_vectors; ++n)
412 (*errors[n])(cell->active_cell_index()) = 0;
413
414 fe_values.reinit(cell);
415 for (unsigned int s = 0; s < n_solution_vectors; ++s)
416 fe_values.get_present_fe_values().get_function_gradients(
417 *solutions[s], gradients_here[s]);
418
419 // loop over the two points bounding this line. n==0 is left point,
420 // n==1 is right point
421 for (unsigned int n = 0; n < 2; ++n)
422 {
423 // find left or right active neighbor
424 auto neighbor = cell->neighbor(n);
425 if (neighbor.state() == IteratorState::valid)
426 while (neighbor->has_children())
427 neighbor = neighbor->child(n == 0 ? 1 : 0);
428
429 fe_face_values.reinit(cell, n);
430 Tensor<1, spacedim> normal =
431 fe_face_values.get_present_fe_values().get_normal_vectors()[0];
432
433 if (neighbor.state() == IteratorState::valid)
434 {
435 fe_values.reinit(neighbor);
436
437 for (unsigned int s = 0; s < n_solution_vectors; ++s)
438 fe_values.get_present_fe_values().get_function_gradients(
439 *solutions[s], gradients_neighbor[s]);
440
441 fe_face_values.reinit(neighbor, n == 0 ? 1 : 0);
442 Tensor<1, spacedim> neighbor_normal =
443 fe_face_values.get_present_fe_values()
444 .get_normal_vectors()[0];
445
446 // extract the gradient in normal direction of all the
447 // components.
448 for (unsigned int s = 0; s < n_solution_vectors; ++s)
449 for (unsigned int c = 0; c < n_components; ++c)
450 grad_dot_n_neighbor[s](c) =
451 -(gradients_neighbor[s][n == 0 ? 1 : 0][c] *
452 neighbor_normal);
453 }
454 else if (neumann_bc.find(n) != neumann_bc.end())
455 // if Neumann b.c., then fill the gradients field which will be
456 // used later on.
457 {
458 if (n_components == 1)
459 {
460 const Number v =
461 neumann_bc.find(n)->second->value(cell->vertex(n));
462
463 for (unsigned int s = 0; s < n_solution_vectors; ++s)
464 grad_dot_n_neighbor[s](0) = v;
465 }
466 else
467 {
468 Vector<Number> v(n_components);
469 neumann_bc.find(n)->second->vector_value(cell->vertex(n),
470 v);
471
472 for (unsigned int s = 0; s < n_solution_vectors; ++s)
473 grad_dot_n_neighbor[s] = v;
474 }
475 }
476 else
477 // fill with zeroes.
478 for (unsigned int s = 0; s < n_solution_vectors; ++s)
479 grad_dot_n_neighbor[s] = 0;
480
481 // if there is a coefficient, then evaluate it at the present
482 // position. if there is none, reuse the preset values.
483 if (coefficient != nullptr)
484 {
485 if (coefficient->n_components == 1)
486 {
487 const double c_value = coefficient->value(cell->vertex(n));
488 for (unsigned int c = 0; c < n_components; ++c)
489 coefficient_values(c) = c_value;
490 }
491 else
492 coefficient->vector_value(cell->vertex(n),
493 coefficient_values);
494 }
495
496
497 for (unsigned int s = 0; s < n_solution_vectors; ++s)
498 for (unsigned int component = 0; component < n_components;
499 ++component)
500 if (component_mask[component] == true)
501 {
502 // get gradient here
504 grad_dot_n_here =
505 gradients_here[s][n][component] * normal;
506
507 const typename ProductType<number, double>::type jump =
508 ((grad_dot_n_here - grad_dot_n_neighbor[s](component)) *
509 coefficient_values(component));
510 (*errors[s])(cell->active_cell_index()) +=
512 typename ProductType<number,
513 double>::type>::abs_square(jump) *
514 cell->diameter();
515 }
516 }
517
518 for (unsigned int s = 0; s < n_solution_vectors; ++s)
519 (*errors[s])(cell->active_cell_index()) =
520 std::sqrt((*errors[s])(cell->active_cell_index()));
521 }
522}
523
524
525
526template <int spacedim>
527template <typename Number>
528void
530 const Mapping<1, spacedim> &mapping,
531 const DoFHandler<1, spacedim> &dof_handler,
532 const Quadrature<0> &quadrature,
533 const std::map<types::boundary_id, const Function<spacedim, Number> *>
534 &neumann_bc,
535 const ArrayView<const ReadVector<Number> *> &solutions,
536 ArrayView<Vector<float> *> &errors,
537 const ComponentMask &component_mask,
538 const Function<spacedim> *coefficients,
539 const unsigned int n_threads,
540 const types::subdomain_id subdomain_id,
541 const types::material_id material_id,
542 const Strategy strategy)
543{
544 const hp::MappingCollection<1, spacedim> mapping_collection(mapping);
545 const hp::QCollection<0> quadrature_collection(quadrature);
546 estimate(mapping_collection,
547 dof_handler,
548 quadrature_collection,
549 neumann_bc,
550 solutions,
551 errors,
552 component_mask,
553 coefficients,
554 n_threads,
555 subdomain_id,
556 material_id,
557 strategy);
558}
559
560
561
562// explicit instantiations
563#include "numerics/error_estimator_1d.inst"
564
565
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
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
void reinit(const TriaIterator< DoFCellAccessor< dim, spacedim, 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:424
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 & ExcNotImplemented()
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
@ update_normal_vectors
Normal vectors.
@ update_gradients
Shape function gradients.
std::size_t size
Definition mpi.cc:733
@ valid
Iterator points to a valid object.
constexpr ReferenceCell< 1 > Line
constexpr types::boundary_id internal_face_boundary_id
Definition types.h:319
constexpr types::material_id invalid_material_id
Definition types.h:284
constexpr types::subdomain_id invalid_subdomain_id
Definition types.h:385
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
typename internal::ProductTypeImpl< std::decay_t< T >, std::decay_t< U > >::type type