Reference documentation for deal.II version 8.4.2
fe_tools_interpolate.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2015 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 
17 #include <deal.II/base/quadrature_lib.h>
18 #include <deal.II/base/qprojector.h>
19 #include <deal.II/base/thread_management.h>
20 #include <deal.II/base/utilities.h>
21 #include <deal.II/lac/vector.h>
22 #include <deal.II/lac/block_vector.h>
23 #include <deal.II/lac/parallel_vector.h>
24 #include <deal.II/lac/parallel_block_vector.h>
25 #include <deal.II/lac/petsc_parallel_vector.h>
26 #include <deal.II/lac/petsc_block_vector.h>
27 #include <deal.II/lac/petsc_parallel_block_vector.h>
28 #include <deal.II/lac/trilinos_vector.h>
29 #include <deal.II/lac/trilinos_block_vector.h>
30 #include <deal.II/lac/constraint_matrix.h>
31 #include <deal.II/grid/tria.h>
32 #include <deal.II/grid/tria_iterator.h>
33 #include <deal.II/grid/grid_generator.h>
34 #include <deal.II/fe/fe_tools.h>
35 #include <deal.II/fe/fe.h>
36 #include <deal.II/fe/fe_values.h>
37 #include <deal.II/dofs/dof_handler.h>
38 #include <deal.II/dofs/dof_accessor.h>
39 #include <deal.II/dofs/dof_tools.h>
40 #include <deal.II/hp/dof_handler.h>
41 
42 #include <deal.II/base/std_cxx11/shared_ptr.h>
43 
44 #include <deal.II/base/index_set.h>
45 
46 #include <iostream>
47 
48 
49 DEAL_II_NAMESPACE_OPEN
50 
51 namespace FETools
52 {
53  template <int dim, int spacedim,
54  template <int, int> class DoFHandlerType1,
55  template <int, int> class DoFHandlerType2,
56  class InVector, class OutVector>
57  void
58  interpolate(const DoFHandlerType1<dim, spacedim> &dof1,
59  const InVector &u1,
60  const DoFHandlerType2<dim, spacedim> &dof2,
61  OutVector &u2)
62  {
63  ConstraintMatrix dummy;
64  dummy.close();
65  interpolate(dof1, u1, dof2, dummy, u2);
66  }
67 
68 
69 
70  template <int dim, int spacedim,
71  template <int, int> class DoFHandlerType1,
72  template <int, int> class DoFHandlerType2,
73  class InVector, class OutVector>
74  void
75  interpolate (const DoFHandlerType1<dim, spacedim> &dof1,
76  const InVector &u1,
77  const DoFHandlerType2<dim, spacedim> &dof2,
78  const ConstraintMatrix &constraints,
79  OutVector &u2)
80  {
81  Assert(&dof1.get_triangulation()==&dof2.get_triangulation(), ExcTriangulationMismatch());
82 
83  Assert(u1.size()==dof1.n_dofs(),
84  ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
85  Assert(u2.size()==dof2.n_dofs(),
86  ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
87 
88 #ifdef DEBUG
89  const IndexSet &dof1_local_dofs = dof1.locally_owned_dofs();
90  const IndexSet &dof2_local_dofs = dof2.locally_owned_dofs();
91  const IndexSet u1_elements = u1.locally_owned_elements();
92  const IndexSet u2_elements = u2.locally_owned_elements();
93  Assert(u1_elements == dof1_local_dofs,
94  ExcMessage("The provided vector and DoF handler should have the same"
95  " index sets."));
96  Assert(u2_elements == dof2_local_dofs,
97  ExcMessage("The provided vector and DoF handler should have the same"
98  " index sets."));
99 #endif
100 
101  // allocate vectors at maximal
102  // size. will be reinited in inner
103  // cell, but Vector makes sure that
104  // this does not lead to
105  // reallocation of memory
106  Vector<typename OutVector::value_type> u1_local(DoFTools::max_dofs_per_cell(dof1));
107  Vector<typename OutVector::value_type> u2_local(DoFTools::max_dofs_per_cell(dof2));
108 
109  // have a map for interpolation
110  // matrices. shared_ptr make sure
111  // that memory is released again
112  std::map<const FiniteElement<dim,spacedim> *,
113  std::map<const FiniteElement<dim,spacedim> *,
114  std_cxx11::shared_ptr<FullMatrix<double> > > >
115  interpolation_matrices;
116 
117  typename DoFHandlerType1<dim,spacedim>::active_cell_iterator cell1 = dof1.begin_active(),
118  endc1 = dof1.end();
119  typename DoFHandlerType2<dim,spacedim>::active_cell_iterator cell2 = dof2.begin_active(),
120  endc2 = dof2.end();
121  (void)endc2;
122 
123  std::vector<types::global_dof_index> dofs;
124  dofs.reserve (DoFTools::max_dofs_per_cell (dof2));
125 
126  u2 = 0;
127  OutVector touch_count(u2);
128  touch_count = 0;
129 
130  // for distributed triangulations,
131  // we can only interpolate u1 on
132  // a cell, which this processor owns,
133  // so we have to know the subdomain_id
134  const types::subdomain_id subdomain_id =
135  dof1.get_triangulation().locally_owned_subdomain();
136 
137  for (; cell1!=endc1; ++cell1, ++cell2)
138  if ((cell1->subdomain_id() == subdomain_id)
139  ||
140  (subdomain_id == numbers::invalid_subdomain_id))
141  {
142  Assert(cell1->get_fe().n_components() == cell2->get_fe().n_components(),
143  ExcDimensionMismatch (cell1->get_fe().n_components(),
144  cell2->get_fe().n_components()));
145 
146  // for continuous elements on
147  // grids with hanging nodes we
148  // need hanging node
149  // constraints. Consequently,
150  // if there are no constraints
151  // then hanging nodes are not
152  // allowed.
153  const bool hanging_nodes_not_allowed
154  = ((cell2->get_fe().dofs_per_vertex != 0) &&
155  (constraints.n_constraints() == 0));
156 
157  if (hanging_nodes_not_allowed)
158  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
159  Assert (cell1->at_boundary(face) ||
160  cell1->neighbor(face)->level() == cell1->level(),
161  ExcHangingNodesNotAllowed(0));
162 
163 
164  const unsigned int dofs_per_cell1 = cell1->get_fe().dofs_per_cell;
165  const unsigned int dofs_per_cell2 = cell2->get_fe().dofs_per_cell;
166  u1_local.reinit (dofs_per_cell1);
167  u2_local.reinit (dofs_per_cell2);
168 
169  // check if interpolation
170  // matrix for this particular
171  // pair of elements is already
172  // there
173  if (interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()].get() == 0)
174  {
175  std_cxx11::shared_ptr<FullMatrix<double> >
176  interpolation_matrix (new FullMatrix<double> (dofs_per_cell2,
177  dofs_per_cell1));
178  interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()]
179  = interpolation_matrix;
180 
181  get_interpolation_matrix(cell1->get_fe(),
182  cell2->get_fe(),
183  *interpolation_matrix);
184  }
185 
186  cell1->get_dof_values(u1, u1_local);
187  interpolation_matrices[&cell1->get_fe()][&cell2->get_fe()]
188  ->vmult(u2_local, u1_local);
189 
190  dofs.resize (dofs_per_cell2);
191  cell2->get_dof_indices(dofs);
192 
193  for (unsigned int i=0; i<dofs_per_cell2; ++i)
194  {
195  u2(dofs[i])+=u2_local(i);
196  touch_count(dofs[i]) += 1;
197  }
198  }
199  // cell1 is at the end, so should
200  // be cell2
201  Assert (cell2 == endc2, ExcInternalError());
202 
203  u2.compress(VectorOperation::add);
204  touch_count.compress(VectorOperation::add);
205 
206  // if we work on parallel distributed
207  // vectors, we have to ensure, that we only
208  // work on dofs this processor owns.
209  IndexSet locally_owned_dofs = dof2.locally_owned_dofs();
210 
211  // when a discontinuous element is
212  // interpolated to a continuous
213  // one, we take the mean values.
214  // for parallel vectors check,
215  // if this component is owned by
216  // this processor.
217  for (types::global_dof_index i=0; i<dof2.n_dofs(); ++i)
218  if (locally_owned_dofs.is_element(i))
219  {
220  Assert(touch_count(i) != typename OutVector::value_type(),
221  ExcInternalError());
222  u2(i) /= touch_count(i);
223  }
224 
225  // finish the work on parallel vectors
226  u2.compress(VectorOperation::insert);
227  // Apply hanging node constraints.
228  constraints.distribute(u2);
229  }
230 
231 
232 
233  template <int dim, class InVector, class OutVector, int spacedim>
234  void
236  const InVector &u1,
237  const FiniteElement<dim,spacedim> &fe2,
238  OutVector &u1_interpolated)
239  {
240  Assert(dof1.get_fe().n_components() == fe2.n_components(),
241  ExcDimensionMismatch(dof1.get_fe().n_components(), fe2.n_components()));
242  Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
243  Assert(u1_interpolated.size()==dof1.n_dofs(),
244  ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
245 
246 #ifdef DEBUG
247  const IndexSet &dof1_local_dofs = dof1.locally_owned_dofs();
248  const IndexSet u1_elements = u1.locally_owned_elements();
249  const IndexSet u1_interpolated_elements = u1_interpolated.locally_owned_elements();
250  Assert(u1_elements == dof1_local_dofs,
251  ExcMessage("The provided vector and DoF handler should have the same"
252  " index sets."));
253  Assert(u1_interpolated_elements == dof1_local_dofs,
254  ExcMessage("The provided vector and DoF handler should have the same"
255  " index sets."));
256 #endif
257 
258  // For continuous elements on grids
259  // with hanging nodes we need
260  // hanging node
261  // constraints. Consequently, when
262  // the elements are continuous no
263  // hanging node constraints are
264  // allowed.
265  const bool hanging_nodes_not_allowed=
266  (dof1.get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
267 
268  const unsigned int dofs_per_cell1=dof1.get_fe().dofs_per_cell;
269 
270  Vector<typename OutVector::value_type> u1_local(dofs_per_cell1);
271  Vector<typename OutVector::value_type> u1_int_local(dofs_per_cell1);
272 
273  const types::subdomain_id subdomain_id =
274  dof1.get_triangulation().locally_owned_subdomain();
275 
277  endc = dof1.end();
278 
279  FullMatrix<double> interpolation_matrix(dofs_per_cell1, dofs_per_cell1);
281  interpolation_matrix);
282  for (; cell!=endc; ++cell)
283  if ((cell->subdomain_id() == subdomain_id)
284  ||
285  (subdomain_id == numbers::invalid_subdomain_id))
286  {
287  if (hanging_nodes_not_allowed)
288  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
289  Assert (cell->at_boundary(face) ||
290  cell->neighbor(face)->level() == cell->level(),
291  ExcHangingNodesNotAllowed(0));
292 
293  cell->get_dof_values(u1, u1_local);
294  interpolation_matrix.vmult(u1_int_local, u1_local);
295  cell->set_dof_values(u1_int_local, u1_interpolated);
296  }
297 
298  // if we work on a parallel PETSc vector
299  // we have to finish the work
300  u1_interpolated.compress(VectorOperation::insert);
301  }
302 
303 
304 
305  template <int dim,
306  template <int> class DoFHandlerType,
307  class InVector, class OutVector, int spacedim>
308  void
309  back_interpolate(const DoFHandlerType<dim> &dof1,
310  const InVector &u1,
311  const FiniteElement<dim,spacedim> &fe2,
312  OutVector &u1_interpolated)
313  {
314  Assert(u1.size() == dof1.n_dofs(),
315  ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
316  Assert(u1_interpolated.size() == dof1.n_dofs(),
317  ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
318 
319 #ifdef DEBUG
320  const IndexSet &dof1_local_dofs = dof1.locally_owned_dofs();
321  const IndexSet u1_elements = u1.locally_owned_elements();
322  const IndexSet u1_interpolated_elements = u1_interpolated.locally_owned_elements();
323  Assert(u1_elements == dof1_local_dofs,
324  ExcMessage("The provided vector and DoF handler should have the same"
325  " index sets."));
326  Assert(u1_interpolated_elements == dof1_local_dofs,
327  ExcMessage("The provided vector and DoF handler should have the same"
328  " index sets."));
329 #endif
330 
331  Vector<typename OutVector::value_type> u1_local(DoFTools::max_dofs_per_cell(dof1));
332  Vector<typename OutVector::value_type> u1_int_local(DoFTools::max_dofs_per_cell(dof1));
333 
334  const types::subdomain_id subdomain_id =
335  dof1.get_triangulation().locally_owned_subdomain();
336 
337  typename DoFHandlerType<dim>::active_cell_iterator cell = dof1.begin_active(),
338  endc = dof1.end();
339 
340  // map from possible fe objects in
341  // dof1 to the back_interpolation
342  // matrices
343  std::map<const FiniteElement<dim> *,
344  std_cxx11::shared_ptr<FullMatrix<double> > > interpolation_matrices;
345 
346  for (; cell!=endc; ++cell)
347  if ((cell->subdomain_id() == subdomain_id)
348  ||
349  (subdomain_id == numbers::invalid_subdomain_id))
350  {
351  Assert(cell->get_fe().n_components() == fe2.n_components(),
352  ExcDimensionMismatch(cell->get_fe().n_components(),
353  fe2.n_components()));
354 
355  // For continuous elements on
356  // grids with hanging nodes we
357  // need hanging node
358  // constraints. Consequently,
359  // when the elements are
360  // continuous no hanging node
361  // constraints are allowed.
362  const bool hanging_nodes_not_allowed=
363  (cell->get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
364 
365  if (hanging_nodes_not_allowed)
366  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
367  Assert (cell->at_boundary(face) ||
368  cell->neighbor(face)->level() == cell->level(),
369  ExcHangingNodesNotAllowed(0));
370 
371  const unsigned int dofs_per_cell1 = cell->get_fe().dofs_per_cell;
372 
373  // make sure back_interpolation
374  // matrix is available
375  if (interpolation_matrices[&cell->get_fe()] != 0)
376  {
377  interpolation_matrices[&cell->get_fe()] =
378  std_cxx11::shared_ptr<FullMatrix<double> >
379  (new FullMatrix<double>(dofs_per_cell1, dofs_per_cell1));
380  get_back_interpolation_matrix(dof1.get_fe(), fe2,
381  *interpolation_matrices[&cell->get_fe()]);
382  }
383 
384  u1_local.reinit (dofs_per_cell1);
385  u1_int_local.reinit (dofs_per_cell1);
386 
387  cell->get_dof_values(u1, u1_local);
388  interpolation_matrices[&cell->get_fe()]->vmult(u1_int_local, u1_local);
389  cell->set_dof_values(u1_int_local, u1_interpolated);
390  };
391 
392  // if we work on a parallel PETSc vector
393  // we have to finish the work
394  u1_interpolated.compress(VectorOperation::insert);
395  }
396 
397 
398 
399  namespace internal
400  {
401  namespace
402  {
403  template <int dim, int spacedim, class InVector>
404  void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
405  const ConstraintMatrix &constraints1,
406  const InVector &u1,
407  const DoFHandler<dim,spacedim> &dof2,
408  const ConstraintMatrix &constraints2,
409  InVector &u1_interpolated)
410  {
412  interpolate(dof1, u1, dof2, constraints2, u2);
413  interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
414  }
415 
416  // special version for PETSc
417 #ifdef DEAL_II_WITH_PETSC
418  template <int dim, int spacedim>
419  void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
420  const ConstraintMatrix &constraints1,
421  const PETScWrappers::MPI::Vector &u1,
422  const DoFHandler<dim,spacedim> &dof2,
423  const ConstraintMatrix &constraints2,
424  PETScWrappers::MPI::Vector &u1_interpolated)
425  {
426  // if u1 is a parallel distributed PETSc vector, we create a
427  // vector u2 with based on the sets of locally owned and relevant
428  // dofs of dof2
429  IndexSet dof2_locally_owned_dofs = dof2.locally_owned_dofs();
430  IndexSet dof2_locally_relevant_dofs;
432  dof2_locally_relevant_dofs);
433 
434  PETScWrappers::MPI::Vector u2_out (dof2_locally_owned_dofs,
435  u1.get_mpi_communicator());
436  interpolate(dof1, u1, dof2, constraints2, u2_out);
437  PETScWrappers::MPI::Vector u2 (dof2_locally_owned_dofs,
438  dof2_locally_relevant_dofs,
439  u1.get_mpi_communicator());
440  u2 = u2_out;
441  interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
442  }
443 #endif
444 
445  // special version for Trilinos
446 #ifdef DEAL_II_WITH_TRILINOS
447  template <int dim, int spacedim>
448  void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
449  const ConstraintMatrix &constraints1,
451  const DoFHandler<dim,spacedim> &dof2,
452  const ConstraintMatrix &constraints2,
453  TrilinosWrappers::MPI::Vector &u1_interpolated)
454  {
455  // if u1 is a parallel distributed Trilinos vector, we create a
456  // vector u2 with based on the sets of locally owned and relevant
457  // dofs of dof2
458  IndexSet dof2_locally_owned_dofs = dof2.locally_owned_dofs();
459  IndexSet dof2_locally_relevant_dofs;
461  dof2_locally_relevant_dofs);
462 
463  TrilinosWrappers::MPI::Vector u2_out (dof2_locally_owned_dofs,
464  u1.get_mpi_communicator());
465  interpolate(dof1, u1, dof2, constraints2, u2_out);
466  TrilinosWrappers::MPI::Vector u2 (dof2_locally_owned_dofs,
467  dof2_locally_relevant_dofs,
468  u1.get_mpi_communicator());
469  u2 = u2_out;
470  interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
471  }
472 #endif
473 
474  // special version for parallel::distributed::Vector
475  template <int dim, int spacedim, typename Number>
476  void back_interpolate (const DoFHandler<dim,spacedim> &dof1,
477  const ConstraintMatrix &constraints1,
479  const DoFHandler<dim,spacedim> &dof2,
480  const ConstraintMatrix &constraints2,
481  parallel::distributed::Vector<Number> &u1_interpolated)
482  {
483  IndexSet dof2_locally_owned_dofs = dof2.locally_owned_dofs();
484  IndexSet dof2_locally_relevant_dofs;
486  dof2_locally_relevant_dofs);
487 
489  u2 (dof2_locally_owned_dofs,
490  dof2_locally_relevant_dofs,
491  u1.get_mpi_communicator());
492 
493  interpolate(dof1, u1, dof2, constraints2, u2);
494  u2.update_ghost_values ();
495  interpolate(dof2, u2, dof1, constraints1, u1_interpolated);
496  }
497  }
498  }
499 
500 
501  template <int dim, class InVector, class OutVector, int spacedim>
503  const ConstraintMatrix &constraints1,
504  const InVector &u1,
505  const DoFHandler<dim,spacedim> &dof2,
506  const ConstraintMatrix &constraints2,
507  OutVector &u1_interpolated)
508  {
509  // For discontinuous elements without constraints take the simpler version
510  // of the back_interpolate function.
511  if (dof1.get_fe().dofs_per_vertex==0 && dof2.get_fe().dofs_per_vertex==0
512  && constraints1.n_constraints()==0 && constraints2.n_constraints()==0)
513  back_interpolate(dof1, u1, dof2.get_fe(), u1_interpolated);
514  else
515  {
516  Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
517  ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
518  Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
519  Assert(u1_interpolated.size()==dof1.n_dofs(),
520  ExcDimensionMismatch(u1_interpolated.size(), dof1.n_dofs()));
521 
522  // For continuous elements first interpolate to dof2, taking into
523  // account constraints2, and then interpolate back to dof1 taking into
524  // account constraints1
525  internal::back_interpolate(dof1, constraints1, u1, dof2, constraints2,
526  u1_interpolated);
527  }
528  }
529 
530 
531 
532  template <int dim, class InVector, class OutVector, int spacedim>
534  const InVector &u1,
535  const FiniteElement<dim,spacedim> &fe2,
536  OutVector &u1_difference)
537  {
538  Assert(dof1.get_fe().n_components() == fe2.n_components(),
539  ExcDimensionMismatch(dof1.get_fe().n_components(), fe2.n_components()));
540  Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
541  Assert(u1_difference.size()==dof1.n_dofs(),
542  ExcDimensionMismatch(u1_difference.size(), dof1.n_dofs()));
543 
544 #ifdef DEBUG
545  const IndexSet &dof1_local_dofs = dof1.locally_owned_dofs();
546  const IndexSet u1_elements = u1.locally_owned_elements();
547  const IndexSet u1_difference_elements = u1_difference.locally_owned_elements();
548  Assert(u1_elements == dof1_local_dofs,
549  ExcMessage("The provided vector and DoF handler should have the same"
550  " index sets."));
551  Assert(u1_difference_elements == dof1_local_dofs,
552  ExcMessage("The provided vector and DoF handler should have the same"
553  " index sets."));
554 #endif
555 
556  // For continuous elements on grids
557  // with hanging nodes we need
558  // hanging node
559  // constraints. Consequently, when
560  // the elements are continuous no
561  // hanging node constraints are
562  // allowed.
563  const bool hanging_nodes_not_allowed=
564  (dof1.get_fe().dofs_per_vertex != 0) || (fe2.dofs_per_vertex != 0);
565 
566  const unsigned int dofs_per_cell=dof1.get_fe().dofs_per_cell;
567 
568  Vector<typename OutVector::value_type> u1_local(dofs_per_cell);
569  Vector<typename OutVector::value_type> u1_diff_local(dofs_per_cell);
570 
571  const types::subdomain_id subdomain_id =
572  dof1.get_triangulation().locally_owned_subdomain();
573 
574  FullMatrix<double> difference_matrix(dofs_per_cell, dofs_per_cell);
576  difference_matrix);
577 
579  endc = dof1.end();
580 
581  for (; cell!=endc; ++cell)
582  if ((cell->subdomain_id() == subdomain_id)
583  ||
584  (subdomain_id == numbers::invalid_subdomain_id))
585  {
586  if (hanging_nodes_not_allowed)
587  for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
588  Assert (cell->at_boundary(face) ||
589  cell->neighbor(face)->level() == cell->level(),
590  ExcHangingNodesNotAllowed(0));
591 
592  cell->get_dof_values(u1, u1_local);
593  difference_matrix.vmult(u1_diff_local, u1_local);
594  cell->set_dof_values(u1_diff_local, u1_difference);
595  }
596 
597  // if we work on a parallel PETSc vector
598  // we have to finish the work and
599  // update ghost values
600  u1_difference.compress(VectorOperation::insert);
601  }
602 
603 
604 
605  namespace internal
606  {
607  namespace
608  {
609  template <int dim, class InVector, class OutVector, int spacedim>
611  const ConstraintMatrix &constraints1,
612  const InVector &u1,
613  const DoFHandler<dim,spacedim> &dof2,
614  const ConstraintMatrix &constraints2,
615  OutVector &u1_difference)
616  {
617  back_interpolate(dof1, constraints1, u1, dof2, constraints2, u1_difference);
618  u1_difference.sadd(-1, u1);
619  }
620 
621  // special version for Trilinos
622 #ifdef DEAL_II_WITH_TRILINOS
623  template <int dim, int spacedim>
625  const ConstraintMatrix &constraints1,
627  const DoFHandler<dim,spacedim> &dof2,
628  const ConstraintMatrix &constraints2,
629  TrilinosWrappers::MPI::Vector &u1_difference)
630  {
631  back_interpolate(dof1, constraints1, u1, dof2, constraints2, u1_difference);
632 
633  // Trilinos vectors with and without ghost entries are very different
634  // and we cannot use the sadd function directly, so we have to create
635  // a completely distributed vector first and copy the local entries
636  // from the vector with ghost entries
637  TrilinosWrappers::MPI::Vector u1_completely_distributed (u1_difference.vector_partitioner ());
638 
639  u1_completely_distributed = u1;
640 
641  u1_difference.sadd(-1, u1_completely_distributed);
642  }
643 #endif
644  }
645  }
646 
647 
648 
649  template <int dim, class InVector, class OutVector, int spacedim>
651  const ConstraintMatrix &constraints1,
652  const InVector &u1,
653  const DoFHandler<dim,spacedim> &dof2,
654  const ConstraintMatrix &constraints2,
655  OutVector &u1_difference)
656  {
657  // For discontinuous elements
658  // without constraints take the
659  // cheaper version of the
660  // interpolation_difference function.
661  if (dof1.get_fe().dofs_per_vertex==0 && dof2.get_fe().dofs_per_vertex==0
662  && constraints1.n_constraints()==0 && constraints2.n_constraints()==0)
663  interpolation_difference(dof1, u1, dof2.get_fe(), u1_difference);
664  else
665  {
666  internal::interpolation_difference(dof1, constraints1, u1, dof2, constraints2, u1_difference);
667  }
668  }
669 
670 
671 
672  template <int dim, class InVector, class OutVector, int spacedim>
674  const InVector &u1,
675  const DoFHandler<dim,spacedim> &dof2,
676  OutVector &u2)
677  {
678  Assert(&dof1.get_triangulation()==&dof2.get_triangulation(), ExcTriangulationMismatch());
679  Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
680  ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
681  Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
682  Assert(u2.size()==dof2.n_dofs(), ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
683 
687 
688  const unsigned int n1 = dof1.get_fe().dofs_per_cell;
689  const unsigned int n2 = dof2.get_fe().dofs_per_cell;
690 
691  Vector<double> u1_local(n1);
692  Vector<double> u2_local(n2);
693  std::vector<types::global_dof_index> dofs(n2);
694 
695  FullMatrix<double> matrix(n2,n1);
696  get_projection_matrix(dof1.get_fe(), dof2.get_fe(), matrix);
697 
698  u2 = 0;
699  while (cell2 != end)
700  {
701  cell1->get_dof_values(u1, u1_local);
702  matrix.vmult(u2_local, u1_local);
703  cell2->get_dof_indices(dofs);
704  for (unsigned int i=0; i<n2; ++i)
705  {
706  u2(dofs[i])+=u2_local(i);
707  }
708 
709  ++cell1;
710  ++cell2;
711  }
712  }
713 
714 
715  template <int dim, class InVector, class OutVector, int spacedim>
717  const InVector &u1,
718  const DoFHandler<dim,spacedim> &dof2,
719  OutVector &u2)
720  {
721  ConstraintMatrix dummy;
722  dummy.close();
723  extrapolate(dof1, u1, dof2, dummy, u2);
724  }
725 
726 
727 
728  template <int dim, class InVector, class OutVector, int spacedim>
730  const InVector &u1,
731  const DoFHandler<dim,spacedim> &dof2,
732  const ConstraintMatrix &constraints,
733  OutVector &u2)
734  {
735  Assert(dof1.get_fe().n_components() == dof2.get_fe().n_components(),
736  ExcDimensionMismatch(dof1.get_fe().n_components(), dof2.get_fe().n_components()));
737  Assert(&dof1.get_triangulation()==&dof2.get_triangulation(), ExcTriangulationMismatch());
738  Assert(u1.size()==dof1.n_dofs(), ExcDimensionMismatch(u1.size(), dof1.n_dofs()));
739  Assert(u2.size()==dof2.n_dofs(), ExcDimensionMismatch(u2.size(), dof2.n_dofs()));
740 
741  OutVector u3;
742  u3.reinit(u2);
743  interpolate(dof1, u1, dof2, constraints, u3);
744 
745  const unsigned int dofs_per_cell = dof2.get_fe().dofs_per_cell;
746  Vector<typename OutVector::value_type> dof_values(dofs_per_cell);
747 
748  // make sure that each cell on the
749  // coarsest level is at least once
750  // refined. otherwise, we can't
751  // treat these cells and would
752  // generate a bogus result
753  {
754  typename DoFHandler<dim,spacedim>::cell_iterator cell = dof2.begin(0),
755  endc = dof2.end(0);
756  for (; cell!=endc; ++cell)
757  Assert (cell->has_children(), ExcGridNotRefinedAtLeastOnce());
758  }
759 
760  // then traverse grid bottom up
761  for (unsigned int level=0; level<dof1.get_triangulation().n_levels()-1; ++level)
762  {
763  typename DoFHandler<dim,spacedim>::cell_iterator cell=dof2.begin(level),
764  endc=dof2.end(level);
765 
766  for (; cell!=endc; ++cell)
767  if (!cell->active())
768  {
769  // check whether this
770  // cell has active
771  // children
772  bool active_children=false;
773  for (unsigned int child_n=0; child_n<cell->n_children(); ++child_n)
774  if (cell->child(child_n)->active())
775  {
776  active_children=true;
777  break;
778  }
779 
780  // if there are active
781  // children, the we have
782  // to work on this
783  // cell. get the data
784  // from the one vector
785  // and set it on the
786  // other
787  if (active_children)
788  {
789  cell->get_interpolated_dof_values(u3, dof_values);
790  cell->set_dof_values_by_interpolation(dof_values, u2);
791  }
792  }
793  }
794 
795  // Apply hanging node constraints.
796  constraints.distribute(u2);
797  }
798 
799 } // end of namespace FETools
800 
801 
802 
803 /*-------------- Explicit Instantiations -------------------------------*/
804 #include "fe_tools_interpolate.inst"
805 
806 
807 /*---------------------------- fe_tools.cc ---------------------------*/
808 
809 DEAL_II_NAMESPACE_CLOSE
const MPI_Comm & get_mpi_communicator() const
void project_dg(const DoFHandler< dim, spacedim > &dof1, const InVector &u1, const DoFHandler< dim, spacedim > &dof2, OutVector &u2)
const types::subdomain_id invalid_subdomain_id
Definition: types.h:239
cell_iterator begin(const unsigned int level=0) const
Definition: dof_handler.cc:833
void sadd(const TrilinosScalar s, const VectorBase &V)
::ExceptionBase & ExcMessage(std::string arg1)
cell_iterator end() const
Definition: dof_handler.cc:861
void interpolation_difference(const DoFHandler< dim, spacedim > &dof1, const InVector &z1, const FiniteElement< dim, spacedim > &fe2, OutVector &z1_difference)
ActiveSelector::active_cell_iterator active_cell_iterator
Definition: dof_handler.h:221
const FiniteElement< dim, spacedim > & get_fe() const
void extrapolate(const DoFHandler< dim, spacedim > &dof1, const InVector &z1, const DoFHandler< dim, spacedim > &dof2, OutVector &z2)
void get_projection_matrix(const FiniteElement< dim, spacedim > &fe1, const FiniteElement< dim, spacedim > &fe2, FullMatrix< number > &matrix)
Definition: fe_tools.cc:549
void vmult(Vector< number2 > &w, const Vector< number2 > &v, const bool adding=false) const
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: dof_handler.cc:845
ActiveSelector::cell_iterator cell_iterator
Definition: dof_handler.h:249
void get_interpolation_matrix(const FiniteElement< dim, spacedim > &fe1, const FiniteElement< dim, spacedim > &fe2, FullMatrix< number > &interpolation_matrix)
Definition: fe_tools.cc:433
unsigned int global_dof_index
Definition: types.h:88
#define Assert(cond, exc)
Definition: exceptions.h:294
void back_interpolate(const DoFHandler< dim, spacedim > &dof1, const InVector &u1, const FiniteElement< dim, spacedim > &fe2, OutVector &u1_interpolated)
const Epetra_Map & vector_partitioner() const
size_type n_constraints() const
void get_back_interpolation_matrix(const FiniteElement< dim, spacedim > &fe1, const FiniteElement< dim, spacedim > &fe2, FullMatrix< number > &interpolation_matrix)
Definition: fe_tools.cc:497
types::global_dof_index n_dofs() const
void extract_locally_relevant_dofs(const DoFHandlerType &dof_handler, IndexSet &dof_set)
Definition: dof_tools.cc:944
const MPI_Comm & get_mpi_communicator() const
unsigned int subdomain_id
Definition: types.h:42
void distribute(VectorType &vec) const
unsigned int n_components() const
void get_interpolation_difference_matrix(const FiniteElement< dim, spacedim > &fe1, const FiniteElement< dim, spacedim > &fe2, FullMatrix< number > &difference_matrix)
Definition: fe_tools.cc:523
const MPI_Comm & get_mpi_communicator() const
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
const Triangulation< dim, spacedim > & get_triangulation() const
const unsigned int dofs_per_vertex
Definition: fe_base.h:226
bool is_element(const size_type index) const
Definition: index_set.h:1317
const IndexSet & locally_owned_dofs() const
void interpolate(const DoFHandlerType1< dim, spacedim > &dof1, const InVector &u1, const DoFHandlerType2< dim, spacedim > &dof2, OutVector &u2)