Reference documentation for deal.II version 9.2.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\}}\)
solution_transfer.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2009 - 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 
16 
17 #include <deal.II/base/config.h>
18 
19 #ifdef DEAL_II_WITH_P4EST
20 
23 
25 # include <deal.II/dofs/dof_tools.h>
26 
29 
30 # include <deal.II/hp/dof_handler.h>
31 
39 # include <deal.II/lac/vector.h>
40 
41 # include <functional>
42 # include <numeric>
43 
44 
46 
47 
48 namespace
49 {
58  template <typename value_type>
59  std::vector<char>
60  pack_dof_values(std::vector<Vector<value_type>> &dof_values,
61  const unsigned int dofs_per_cell)
62  {
63  for (const auto &values : dof_values)
64  {
65  AssertDimension(values.size(), dofs_per_cell);
66  (void)values;
67  }
68 
69  const std::size_t bytes_per_entry = sizeof(value_type) * dofs_per_cell;
70 
71  std::vector<char> buffer(dof_values.size() * bytes_per_entry);
72  for (unsigned int i = 0; i < dof_values.size(); ++i)
73  std::memcpy(&buffer[i * bytes_per_entry],
74  &dof_values[i](0),
75  bytes_per_entry);
76 
77  return buffer;
78  }
79 
80 
81 
85  template <typename value_type>
86  std::vector<Vector<value_type>>
87  unpack_dof_values(
88  const boost::iterator_range<std::vector<char>::const_iterator> &data_range,
89  const unsigned int dofs_per_cell)
90  {
91  const std::size_t bytes_per_entry = sizeof(value_type) * dofs_per_cell;
92  const unsigned int n_elements = data_range.size() / bytes_per_entry;
93 
94  Assert((data_range.size() % bytes_per_entry == 0), ExcInternalError());
95 
96  std::vector<Vector<value_type>> unpacked_data;
97  unpacked_data.reserve(n_elements);
98  for (unsigned int i = 0; i < n_elements; ++i)
99  {
100  Vector<value_type> dof_values(dofs_per_cell);
101  std::memcpy(&dof_values(0),
102  &(*std::next(data_range.begin(), i * bytes_per_entry)),
103  bytes_per_entry);
104  unpacked_data.emplace_back(std::move(dof_values));
105  }
106 
107  return unpacked_data;
108  }
109 } // namespace
110 
111 
112 
113 namespace parallel
114 {
115  namespace distributed
116  {
117  template <int dim, typename VectorType, typename DoFHandlerType>
119  const DoFHandlerType &dof)
120  : dof_handler(&dof, typeid(*this).name())
121  , handle(numbers::invalid_unsigned_int)
122  {
123  Assert(
124  (dynamic_cast<const parallel::distributed::
125  Triangulation<dim, DoFHandlerType::space_dimension> *>(
126  &dof_handler->get_triangulation()) != nullptr),
127  ExcMessage(
128  "parallel::distributed::SolutionTransfer requires a parallel::distributed::Triangulation object."));
129  }
130 
131 
132 
133  template <int dim, typename VectorType, typename DoFHandlerType>
134  void
137  const std::vector<const VectorType *> &all_in)
138  {
139  input_vectors = all_in;
140  register_data_attach();
141  }
142 
143 
144 
145  template <int dim, typename VectorType, typename DoFHandlerType>
146  void
148  {
149  // TODO: casting away constness is bad
151  *tria = (dynamic_cast<parallel::distributed::Triangulation<
152  dim,
153  DoFHandlerType::space_dimension> *>(
155  *>(&dof_handler->get_triangulation())));
156  Assert(tria != nullptr, ExcInternalError());
157 
158  handle = tria->register_data_attach(
159  [this](
161  cell_iterator &cell_,
163  CellStatus status) { return this->pack_callback(cell_, status); },
164  /*returns_variable_size_data=*/DoFHandlerType::is_hp_dof_handler);
165  }
166 
167 
168 
169  template <int dim, typename VectorType, typename DoFHandlerType>
170  void
173  {
174  std::vector<const VectorType *> all_in(1, &in);
175  prepare_for_coarsening_and_refinement(all_in);
176  }
177 
178 
179 
180  template <int dim, typename VectorType, typename DoFHandlerType>
181  void
184  {
185  std::vector<const VectorType *> all_in(1, &in);
186  prepare_for_serialization(all_in);
187  }
188 
189 
190 
191  template <int dim, typename VectorType, typename DoFHandlerType>
192  void
194  prepare_for_serialization(const std::vector<const VectorType *> &all_in)
195  {
196  prepare_for_coarsening_and_refinement(all_in);
197  }
198 
199 
200 
201  template <int dim, typename VectorType, typename DoFHandlerType>
202  void
204  const VectorType &in)
205  {
206  prepare_for_serialization(in);
207  }
208 
209 
210 
211  template <int dim, typename VectorType, typename DoFHandlerType>
212  void
214  const std::vector<const VectorType *> &all_in)
215  {
216  prepare_for_serialization(all_in);
217  }
218 
219 
220 
221  template <int dim, typename VectorType, typename DoFHandlerType>
222  void
224  VectorType &in)
225  {
226  std::vector<VectorType *> all_in(1, &in);
227  deserialize(all_in);
228  }
229 
230 
231 
232  template <int dim, typename VectorType, typename DoFHandlerType>
233  void
235  std::vector<VectorType *> &all_in)
236  {
237  register_data_attach();
238 
239  // this makes interpolate() happy
240  input_vectors.resize(all_in.size());
241 
242  interpolate(all_in);
243  }
244 
245 
246  template <int dim, typename VectorType, typename DoFHandlerType>
247  void
249  std::vector<VectorType *> &all_out)
250  {
251  Assert(input_vectors.size() == all_out.size(),
252  ExcDimensionMismatch(input_vectors.size(), all_out.size()));
253 
254  // TODO: casting away constness is bad
256  *tria = (dynamic_cast<parallel::distributed::Triangulation<
257  dim,
258  DoFHandlerType::space_dimension> *>(
260  *>(&dof_handler->get_triangulation())));
261  Assert(tria != nullptr, ExcInternalError());
262 
264  handle,
265  [this, &all_out](
267  cell_iterator &cell_,
269  CellStatus status,
270  const boost::iterator_range<std::vector<char>::const_iterator>
271  &data_range) {
272  this->unpack_callback(cell_, status, data_range, all_out);
273  });
274 
275  for (typename std::vector<VectorType *>::iterator it = all_out.begin();
276  it != all_out.end();
277  ++it)
278  (*it)->compress(::VectorOperation::insert);
279 
280  input_vectors.clear();
281  }
282 
283 
284 
285  template <int dim, typename VectorType, typename DoFHandlerType>
286  void
288  VectorType &out)
289  {
290  std::vector<VectorType *> all_out(1, &out);
291  interpolate(all_out);
292  }
293 
294 
295 
296  template <int dim, typename VectorType, typename DoFHandlerType>
297  std::vector<char>
300  cell_iterator &cell_,
301  const typename Triangulation<dim,
302  DoFHandlerType::space_dimension>::CellStatus
303  status)
304  {
305  typename DoFHandlerType::cell_iterator cell(*cell_, dof_handler);
306 
307  // create buffer for each individual object
308  std::vector<::Vector<typename VectorType::value_type>> dof_values(
309  input_vectors.size());
310 
311  unsigned int fe_index = 0;
312  if (DoFHandlerType::is_hp_dof_handler)
313  {
314  switch (status)
315  {
317  dim,
318  DoFHandlerType::space_dimension>::CELL_PERSIST:
320  dim,
321  DoFHandlerType::space_dimension>::CELL_REFINE:
322  {
323  fe_index = cell->future_fe_index();
324  break;
325  }
326 
328  dim,
329  DoFHandlerType::space_dimension>::CELL_COARSEN:
330  {
331  // In case of coarsening, we need to find a suitable fe index
332  // for the parent cell. We choose the 'least dominant fe'
333  // on all children from the associated FECollection.
334  std::set<unsigned int> fe_indices_children;
335  for (unsigned int child_index = 0;
336  child_index < cell->n_children();
337  ++child_index)
338  {
339  const auto &child = cell->child(child_index);
340  Assert(child->is_active() && child->coarsen_flag_set(),
342  dim>::ExcInconsistentCoarseningFlags());
343 
344  fe_indices_children.insert(child->future_fe_index());
345  }
346  Assert(!fe_indices_children.empty(), ExcInternalError());
347 
348  fe_index =
349  dof_handler->get_fe_collection().find_dominated_fe_extended(
350  fe_indices_children, /*codim=*/0);
351 
353  typename ::hp::FECollection<
354  dim>::ExcNoDominatedFiniteElementAmongstChildren());
355 
356  break;
357  }
358 
359  default:
360  Assert(false, ExcInternalError());
361  break;
362  }
363  }
364 
365  const unsigned int dofs_per_cell =
366  dof_handler->get_fe(fe_index).dofs_per_cell;
367 
368  auto it_input = input_vectors.cbegin();
369  auto it_output = dof_values.begin();
370  for (; it_input != input_vectors.cend(); ++it_input, ++it_output)
371  {
372  it_output->reinit(dofs_per_cell);
373  cell->get_interpolated_dof_values(*(*it_input), *it_output, fe_index);
374  }
375 
376  return pack_dof_values<typename VectorType::value_type>(dof_values,
377  dofs_per_cell);
378  }
379 
380 
381 
382  template <int dim, typename VectorType, typename DoFHandlerType>
383  void
386  cell_iterator &cell_,
387  const typename Triangulation<dim,
388  DoFHandlerType::space_dimension>::CellStatus
389  status,
390  const boost::iterator_range<std::vector<char>::const_iterator>
391  & data_range,
392  std::vector<VectorType *> &all_out)
393  {
394  typename DoFHandlerType::cell_iterator cell(*cell_, dof_handler);
395 
396  unsigned int fe_index = 0;
397  if (DoFHandlerType::is_hp_dof_handler)
398  {
399  switch (status)
400  {
402  dim,
403  DoFHandlerType::space_dimension>::CELL_PERSIST:
405  dim,
406  DoFHandlerType::space_dimension>::CELL_COARSEN:
407  {
408  fe_index = cell->active_fe_index();
409  break;
410  }
411 
413  dim,
414  DoFHandlerType::space_dimension>::CELL_REFINE:
415  {
416  // After refinement, this particular cell is no longer active,
417  // and its children have inherited its fe index. However, to
418  // unpack the data on the old cell, we need to recover its fe
419  // index from one of the children. Just to be sure, we also
420  // check if all children have the same fe index.
421  fe_index = cell->child(0)->active_fe_index();
422  for (unsigned int child_index = 1;
423  child_index < cell->n_children();
424  ++child_index)
425  Assert(cell->child(child_index)->active_fe_index() ==
426  fe_index,
427  ExcInternalError());
428  break;
429  }
430 
431  default:
432  Assert(false, ExcInternalError());
433  break;
434  }
435  }
436 
437  const unsigned int dofs_per_cell =
438  dof_handler->get_fe(fe_index).dofs_per_cell;
439 
440  const std::vector<::Vector<typename VectorType::value_type>>
441  dof_values =
442  unpack_dof_values<typename VectorType::value_type>(data_range,
443  dofs_per_cell);
444 
445  // check if sizes match
446  Assert(dof_values.size() == all_out.size(), ExcInternalError());
447 
448  // check if we have enough dofs provided by the FE object
449  // to interpolate the transferred data correctly
450  for (auto it_dof_values = dof_values.begin();
451  it_dof_values != dof_values.end();
452  ++it_dof_values)
453  Assert(
454  dofs_per_cell == it_dof_values->size(),
455  ExcMessage(
456  "The transferred data was packed with a different number of dofs than the "
457  "currently registered FE object assigned to the DoFHandler has."));
458 
459  // distribute data for each registered vector on mesh
460  auto it_input = dof_values.cbegin();
461  auto it_output = all_out.begin();
462  for (; it_input != dof_values.cend(); ++it_input, ++it_output)
463  cell->set_dof_values_by_interpolation(*it_input,
464  *(*it_output),
465  fe_index);
466  }
467  } // namespace distributed
468 } // namespace parallel
469 
470 
471 // explicit instantiations
472 # include "solution_transfer.inst"
473 
475 
476 #endif
tria_accessor.h
VectorOperation::insert
@ insert
Definition: vector_operation.h:49
parallel::distributed::SolutionTransfer::prepare_for_serialization
void prepare_for_serialization(const VectorType &in)
Definition: solution_transfer.cc:183
parallel::distributed::SolutionTransfer::unpack_callback
void unpack_callback(const typename Triangulation< dim, DoFHandlerType::space_dimension >::cell_iterator &cell, const typename Triangulation< dim, DoFHandlerType::space_dimension >::CellStatus status, const boost::iterator_range< std::vector< char >::const_iterator > &data_range, std::vector< VectorType * > &all_out)
Definition: solution_transfer.cc:384
tria_iterator.h
VectorType
parallel::distributed::SolutionTransfer::dof_handler
SmartPointer< const DoFHandlerType, SolutionTransfer< dim, VectorType, DoFHandlerType > > dof_handler
Definition: solution_transfer.h:357
parallel::distributed::Triangulation::notify_ready_to_unpack
void notify_ready_to_unpack(const unsigned int handle, const std::function< void(const cell_iterator &, const CellStatus, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback)
Definition: tria.cc:4378
la_parallel_vector.h
StandardExceptions::ExcMessage
static ::ExceptionBase & ExcMessage(std::string arg1)
block_vector.h
la_parallel_block_vector.h
DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:358
parallel::distributed::SolutionTransfer::SolutionTransfer
SolutionTransfer(const DoFHandlerType &dof)
Definition: solution_transfer.cc:118
parallel::distributed::Triangulation
Definition: tria.h:242
petsc_block_vector.h
AssertDimension
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1579
parallel::distributed::SolutionTransfer::pack_callback
std::vector< char > pack_callback(const typename Triangulation< dim, DoFHandlerType::space_dimension >::cell_iterator &cell, const typename Triangulation< dim, DoFHandlerType::space_dimension >::CellStatus status)
Definition: solution_transfer.cc:298
numbers
Definition: numbers.h:207
parallel::distributed::SolutionTransfer::deserialize
void deserialize(VectorType &in)
Definition: solution_transfer.cc:223
parallel::Triangulation
TriangulationBase< dim, spacedim > Triangulation
Definition: tria_base.h:302
StandardExceptions::ExcInternalError
static ::ExceptionBase & ExcInternalError()
tria.h
dof_tools.h
parallel::distributed::SolutionTransfer::register_data_attach
void register_data_attach()
Definition: solution_transfer.cc:147
solution_transfer.h
Assert
#define Assert(cond, exc)
Definition: exceptions.h:1419
vector.h
dof_accessor.h
numbers::invalid_unsigned_int
static const unsigned int invalid_unsigned_int
Definition: types.h:191
StandardExceptions::ExcDimensionMismatch
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
petsc_vector.h
config.h
parallel::distributed::SolutionTransfer::interpolate
void interpolate(std::vector< VectorType * > &all_out)
Definition: solution_transfer.cc:248
FETools::interpolate
void interpolate(const DoFHandlerType1< dim, spacedim > &dof1, const InVector &u1, const DoFHandlerType2< dim, spacedim > &dof2, OutVector &u2)
parallel::distributed::Triangulation::register_data_attach
unsigned int register_data_attach(const std::function< std::vector< char >(const cell_iterator &, const CellStatus)> &pack_callback, const bool returns_variable_size_data)
Definition: tria.cc:4348
DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:359
value_type
trilinos_vector.h
parallel::distributed::SolutionTransfer::prepare_for_coarsening_and_refinement
void prepare_for_coarsening_and_refinement(const std::vector< const VectorType * > &all_in)
Definition: solution_transfer.cc:136
parallel
Definition: distributed.h:416
parallel::distributed::SolutionTransfer::prepare_serialization
void prepare_serialization(const VectorType &in)
Definition: solution_transfer.cc:203
trilinos_parallel_block_vector.h
dof_handler.h