ExaDG
Loading...
Searching...
No Matches
solution_interpolation.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef INCLUDE_EXADG_POSTPROCESSOR_SOLUTION_INTERPOLATION_H_
23#define INCLUDE_EXADG_POSTPROCESSOR_SOLUTION_INTERPOLATION_H_
24
25// deal.II
26#include <deal.II/base/point.h>
27#include <deal.II/dofs/dof_handler.h>
28#include <deal.II/fe/fe_values.h>
29#include <deal.II/fe/mapping.h>
30#include <deal.II/grid/grid_tools.h>
31#include <deal.II/lac/la_parallel_vector.h>
32
33namespace ExaDG
34{
35template<int dim, typename Number>
36void
37my_point_value(dealii::Vector<Number> & result,
38 dealii::Mapping<dim> const & mapping,
39 dealii::DoFHandler<dim> const & dof_handler,
40 dealii::LinearAlgebra::distributed::Vector<Number> const & dof_vector,
41 typename dealii::DoFHandler<dim>::active_cell_iterator const & cell,
42 dealii::Point<dim> const & point_in_ref_coord)
43{
44 AssertThrow(
45 dof_handler.get_triangulation().all_reference_cells_are_hyper_cube(),
46 dealii::ExcMessage(
47 "This functionality is only available for meshes consisting of hypercube elements."));
48
49 Assert(dealii::GeometryInfo<dim>::distance_to_unit_cell(point_in_ref_coord) < 1e-10,
50 dealii::ExcInternalError());
51
52 dealii::Quadrature<dim> const quadrature(
53 dealii::GeometryInfo<dim>::project_to_unit_cell(point_in_ref_coord));
54
55 dealii::FiniteElement<dim> const & fe = dof_handler.get_fe();
56 dealii::FEValues<dim> fe_values(mapping, fe, quadrature, dealii::update_values);
57 fe_values.reinit(cell);
58
59 // then use this to get the values of the given fe_function at this point
60 std::vector<dealii::Vector<Number>> solution_vector(1, dealii::Vector<Number>(fe.n_components()));
61 fe_values.get_function_values(dof_vector, solution_vector);
62 result = solution_vector[0];
63}
64
65template<int dim, typename Number>
66void
67evaluate_scalar_quantity_in_point(
68 Number & solution_value,
69 dealii::DoFHandler<dim> const & dof_handler,
70 dealii::Mapping<dim> const & mapping,
71 dealii::LinearAlgebra::distributed::Vector<Number> const & numerical_solution,
72 dealii::Point<dim> const & point,
73 MPI_Comm const & mpi_comm,
74 double const tolerance = 1.e-10)
75{
76 typedef std::pair<typename dealii::DoFHandler<dim>::active_cell_iterator, dealii::Point<dim>>
77 Pair;
78
79 std::vector<Pair> adjacent_cells =
80 dealii::GridTools::find_all_active_cells_around_point(mapping, dof_handler, point, tolerance);
81
82 // processor local variables: initialize with zeros since we add values to these variables
83 unsigned int counter = 0;
84 solution_value = 0.0;
85
86 // loop over all adjacent cells
87 for(auto cell : adjacent_cells)
88 {
89 // go on only if cell is owned by the processor
90 if(cell.first->is_locally_owned())
91 {
92 dealii::Vector<Number> value(1);
93 my_point_value(value, mapping, dof_handler, numerical_solution, cell.first, cell.second);
94
95 solution_value += value(0);
96 ++counter;
97 }
98 }
99
100 // parallel computations: add results of all processors and calculate mean value
101 counter = dealii::Utilities::MPI::sum(counter, mpi_comm);
102 AssertThrow(counter > 0, dealii::ExcMessage("No points found."));
103
104 solution_value = dealii::Utilities::MPI::sum(solution_value, mpi_comm);
105 solution_value /= (double)counter;
106}
107
108template<int dim, typename Number>
109void
110evaluate_vectorial_quantity_in_point(
111 dealii::Tensor<1, dim, Number> & solution_value,
112 dealii::DoFHandler<dim> const & dof_handler,
113 dealii::Mapping<dim> const & mapping,
114 dealii::LinearAlgebra::distributed::Vector<Number> const & numerical_solution,
115 dealii::Point<dim> const & point,
116 MPI_Comm const & mpi_comm,
117 double const tolerance = 1.e-10)
118{
119 typedef std::pair<typename dealii::DoFHandler<dim>::active_cell_iterator, dealii::Point<dim>>
120 Pair;
121
122 std::vector<Pair> adjacent_cells =
123 dealii::GridTools::find_all_active_cells_around_point(mapping, dof_handler, point, tolerance);
124
125 // processor local variables: initialize with zeros since we add values to these variables
126 unsigned int counter = 0;
127 solution_value = 0.0;
128
129 // loop over all adjacent cells
130 for(auto cell : adjacent_cells)
131 {
132 // go on only if cell is owned by the processor
133 if(cell.first->is_locally_owned())
134 {
135 dealii::Vector<Number> value(dim);
136 my_point_value(value, mapping, dof_handler, numerical_solution, cell.first, cell.second);
137
138 for(unsigned int d = 0; d < dim; ++d)
139 solution_value[d] += value(d);
140
141 ++counter;
142 }
143 }
144
145 // parallel computations: add results of all processors and calculate mean value
146 counter = dealii::Utilities::MPI::sum(counter, mpi_comm);
147 AssertThrow(counter > 0, dealii::ExcMessage("No points found."));
148
149 for(unsigned int d = 0; d < dim; ++d)
150 solution_value[d] = dealii::Utilities::MPI::sum(solution_value[d], mpi_comm);
151 solution_value /= (double)counter;
152}
153
154/*
155 * For a given vector of adjacent cells and points in reference coordinates, determine
156 * and return the dof_indices and shape_values to be used later for interpolation of the
157 * solution.
158 */
159template<int dim, typename Number>
160std::vector<std::pair<std::vector<dealii::types::global_dof_index>, std::vector<Number>>>
161get_dof_indices_and_shape_values(
162 std::vector<std::pair<typename dealii::Triangulation<dim>::active_cell_iterator,
163 dealii::Point<dim>>> const & adjacent_cells,
164 dealii::DoFHandler<dim> const & dof_handler,
165 dealii::Mapping<dim> const & mapping,
166 dealii::LinearAlgebra::distributed::Vector<Number> const & solution)
167{
168 AssertThrow(
169 dof_handler.get_triangulation().all_reference_cells_are_hyper_cube(),
170 dealii::ExcMessage(
171 "This functionality is only available for meshes consisting of hypercube elements."));
172
173 // fill dof_indices_and_shape_values
174 std::vector<std::pair<std::vector<dealii::types::global_dof_index>, std::vector<Number>>>
175 dof_indices_and_shape_values;
176
177 for(auto cell_tria : adjacent_cells)
178 {
179 // transform Triangulation::active_cell_iterator into dealii::DoFHandler::active_cell_iterator,
180 // see constructor of DoFCellAccessor
181 typename dealii::DoFHandler<dim>::active_cell_iterator cell_dof = {
182 &dof_handler.get_triangulation(),
183 cell_tria.first->level(),
184 cell_tria.first->index(),
185 &dof_handler};
186
187 typedef std::pair<typename dealii::DoFHandler<dim>::active_cell_iterator, dealii::Point<dim>>
188 PairDof;
189 PairDof cell_and_point(cell_dof, cell_tria.second);
190
191 // go on only if cell is owned by the processor
192 if(cell_and_point.first->is_locally_owned())
193 {
194 const dealii::Quadrature<dim> quadrature(
195 dealii::GeometryInfo<dim>::project_to_unit_cell(cell_and_point.second));
196
197 const dealii::FiniteElement<dim> & fe = dof_handler.get_fe();
198 dealii::FEValues<dim> fe_values(mapping, fe, quadrature, dealii::update_values);
199 fe_values.reinit(cell_and_point.first);
200 std::vector<dealii::types::global_dof_index> dof_indices(fe.dofs_per_cell);
201 cell_and_point.first->get_dof_indices(dof_indices);
202
203 std::vector<dealii::types::global_dof_index> dof_indices_global(fe.dofs_per_cell);
204 for(unsigned int i = 0; i < fe.dofs_per_cell; ++i)
205 dof_indices_global[i] = solution.get_partitioner()->global_to_local(dof_indices[i]);
206
207 std::vector<Number> fe_shape_values(fe.dofs_per_cell);
208 for(unsigned int i = 0; i < fe.dofs_per_cell; ++i)
209 fe_shape_values[i] = fe_values.shape_value(i, 0);
210
211 dof_indices_and_shape_values.emplace_back(dof_indices_global, fe_shape_values);
212 }
213 }
214
215 return dof_indices_and_shape_values;
216}
217
218/*
219 * Interpolate solution from dof vector by using precomputed shape function values.
220 */
221template<int rank, int dim, typename Number>
223{
224 static inline DEAL_II_ALWAYS_INLINE //
225 dealii::Tensor<rank, dim, Number>
226 value(dealii::DoFHandler<dim> const & dof_handler,
227 dealii::LinearAlgebra::distributed::Vector<Number> const & solution,
228 std::vector<dealii::types::global_dof_index> const & dof_indices,
229 std::vector<Number> const & fe_shape_values)
230 {
231 (void)dof_handler;
232 (void)solution;
233 (void)dof_indices;
234 (void)fe_shape_values;
235
236 AssertThrow(false, dealii::ExcMessage("not implemented."));
237
238 dealii::Tensor<rank, dim, Number> result;
239 return result;
240 }
241};
242
243/*
244 * The quantity to be evaluated is of type dealii::Tensor<0,dim,Number>.
245 */
246template<int dim, typename Number>
247struct Interpolator<0, dim, Number>
248{
249 static inline DEAL_II_ALWAYS_INLINE //
250 dealii::Tensor<0, dim, Number>
251 value(dealii::DoFHandler<dim> const & dof_handler,
252 dealii::LinearAlgebra::distributed::Vector<Number> const & solution,
253 std::vector<dealii::types::global_dof_index> const & dof_indices,
254 std::vector<Number> const & fe_shape_values)
255 {
256 Assert(dof_handler.get_fe().dofs_per_cell == fe_shape_values.size(),
257 dealii::ExcMessage("Vector fe_shape_values has wrong size."));
258
259 Number result = Number(0.0);
260
261 dealii::FiniteElement<dim> const & fe = dof_handler.get_fe();
262 for(unsigned int i = 0; i < fe.dofs_per_cell; ++i)
263 result += solution.local_element(dof_indices[i]) * fe_shape_values[i];
264
265 dealii::Tensor<0, dim, Number> result_tensor = result;
266
267 return result_tensor;
268 }
269};
270
271/*
272 * The quantity to be evaluated is of type dealii::Tensor<1, dim, Number>.
273 */
274template<int dim, typename Number>
275struct Interpolator<1, dim, Number>
276{
277 static inline DEAL_II_ALWAYS_INLINE //
278 dealii::Tensor<1, dim, Number>
279 value(dealii::DoFHandler<dim> const & dof_handler,
280 dealii::LinearAlgebra::distributed::Vector<Number> const & solution,
281 std::vector<dealii::types::global_dof_index> const & dof_indices,
282 std::vector<Number> const & fe_shape_values)
283 {
284 Assert(dof_handler.get_fe().dofs_per_cell == fe_shape_values.size(),
285 dealii::ExcMessage("Vector fe_shape_values has wrong size."));
286
287 dealii::Tensor<1, dim, Number> result;
288
289 dealii::FiniteElement<dim> const & fe = dof_handler.get_fe();
290 for(unsigned int i = 0; i < fe.dofs_per_cell; ++i)
291 result[fe.system_to_component_index(i).first] +=
292 solution.local_element(dof_indices[i]) * fe_shape_values[i];
293
294 return result;
295 }
296};
297
298} // namespace ExaDG
299
300#endif /* INCLUDE_EXADG_POSTPROCESSOR_SOLUTION_INTERPOLATION_H_ */
Definition driver.cpp:33
Definition solution_interpolation.h:223