Reference documentation for deal.II version 8.4.2
data_out_dof_data.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 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 #include <deal.II/base/quadrature_lib.h>
17 #include <deal.II/base/work_stream.h>
18 #include <deal.II/base/memory_consumption.h>
19 #include <deal.II/lac/vector.h>
20 #include <deal.II/lac/block_vector.h>
21 #include <deal.II/lac/parallel_vector.h>
22 #include <deal.II/lac/parallel_block_vector.h>
23 #include <deal.II/lac/petsc_vector.h>
24 #include <deal.II/lac/petsc_block_vector.h>
25 #include <deal.II/lac/trilinos_vector.h>
26 #include <deal.II/lac/trilinos_block_vector.h>
27 #include <deal.II/numerics/data_out.h>
28 #include <deal.II/numerics/data_out_dof_data.h>
29 #include <deal.II/dofs/dof_handler.h>
30 #include <deal.II/dofs/dof_accessor.h>
31 #include <deal.II/grid/tria.h>
32 #include <deal.II/grid/tria_iterator.h>
33 #include <deal.II/fe/fe.h>
34 #include <deal.II/fe/fe_dgq.h>
35 #include <deal.II/fe/fe_values.h>
36 #include <deal.II/hp/dof_handler.h>
37 #include <deal.II/hp/fe_values.h>
38 #include <deal.II/fe/mapping_q1.h>
39 
40 #include <sstream>
41 
42 DEAL_II_NAMESPACE_OPEN
43 
44 
45 namespace internal
46 {
47  namespace DataOut
48  {
49  template <int dim, int spacedim>
50  ParallelDataBase<dim,spacedim>::
51  ParallelDataBase (const unsigned int n_datasets,
52  const unsigned int n_subdivisions,
53  const std::vector<unsigned int> &n_postprocessor_outputs,
54  const Mapping<dim,spacedim> &mapping,
55  const std::vector<std_cxx11::shared_ptr<::hp::FECollection<dim,spacedim> > > &finite_elements,
56  const UpdateFlags update_flags,
57  const bool use_face_values)
58  :
59  n_datasets (n_datasets),
60  n_subdivisions (n_subdivisions),
61  postprocessed_values (n_postprocessor_outputs.size()),
62  mapping_collection (mapping),
63  finite_elements (finite_elements),
64  update_flags (update_flags)
65  {
66  unsigned int n_q_points = 0;
67  if (use_face_values == false)
68  {
70  quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
71  n_q_points = quadrature[0].size();
72  x_fe_values.resize(this->finite_elements.size());
73  for (unsigned int i=0; i<this->finite_elements.size(); ++i)
74  {
75  // check if there is a finite element that is equal to the
76  // present one, then we can re-use the FEValues object
77  for (unsigned int j=0; j<i; ++j)
78  if (this->finite_elements[i].get() ==
79  this->finite_elements[j].get())
80  {
81  x_fe_values[i] = x_fe_values[j];
82  break;
83  }
84  if (x_fe_values[i].get() == 0)
85  x_fe_values[i].reset(new ::hp::FEValues<dim,spacedim>
86  (this->mapping_collection,
87  *this->finite_elements[i],
88  quadrature,
89  this->update_flags));
90  }
91  }
92  else
93  {
94  ::hp::QCollection<dim-1>
95  quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
96  n_q_points = quadrature[0].size();
97  x_fe_face_values.resize(this->finite_elements.size());
98  for (unsigned int i=0; i<this->finite_elements.size(); ++i)
99  {
100  // check if there is a finite element that is equal to the
101  // present one, then we can re-use the FEValues object
102  for (unsigned int j=0; j<i; ++j)
103  if (this->finite_elements[i].get() ==
104  this->finite_elements[j].get())
105  {
106  x_fe_face_values[i] = x_fe_face_values[j];
107  break;
108  }
109  if (x_fe_face_values[i].get() == 0)
110  x_fe_face_values[i].reset(new ::hp::FEFaceValues<dim,spacedim>
111  (this->mapping_collection,
112  *this->finite_elements[i],
113  quadrature,
114  this->update_flags));
115  }
116  }
117 
118  patch_values.resize (n_q_points);
119  patch_values_system.resize (n_q_points);
120  patch_gradients.resize (n_q_points);
121  patch_gradients_system.resize (n_q_points);
122  patch_hessians.resize (n_q_points);
123  patch_hessians_system.resize (n_q_points);
124 
125  for (unsigned int dataset=0; dataset<n_postprocessor_outputs.size(); ++dataset)
126  if (n_postprocessor_outputs[dataset] != 0)
127  postprocessed_values[dataset]
128  .resize(n_q_points,
129  ::Vector<double>(n_postprocessor_outputs[dataset]));
130  }
131 
132 
133 
134 
135 
136  // implement copy constructor to create a thread's own version of
137  // x_fe_values
138  template <int dim, int spacedim>
139  ParallelDataBase<dim,spacedim>::
140  ParallelDataBase (const ParallelDataBase<dim,spacedim> &data)
141  :
142  n_datasets (data.n_datasets),
143  n_subdivisions (data.n_subdivisions),
144  patch_values (data.patch_values),
145  patch_values_system (data.patch_values_system),
146  patch_gradients (data.patch_gradients),
147  patch_gradients_system (data.patch_gradients_system),
148  patch_hessians (data.patch_hessians),
149  patch_hessians_system (data.patch_hessians_system),
150  postprocessed_values (data.postprocessed_values),
151  mapping_collection (data.mapping_collection),
152  finite_elements (data.finite_elements),
153  update_flags (data.update_flags)
154  {
155  if (data.x_fe_values.empty() == false)
156  {
157  Assert(data.x_fe_face_values.empty() == true, ExcInternalError());
159  quadrature(QIterated<dim>(QTrapez<1>(), n_subdivisions));
160  x_fe_values.resize(this->finite_elements.size());
161  for (unsigned int i=0; i<this->finite_elements.size(); ++i)
162  {
163  // check if there is a finite element that is equal to the
164  // present one, then we can re-use the FEValues object
165  for (unsigned int j=0; j<i; ++j)
166  if (this->finite_elements[i].get() ==
167  this->finite_elements[j].get())
168  {
169  x_fe_values[i] = x_fe_values[j];
170  break;
171  }
172  if (x_fe_values[i].get() == 0)
173  x_fe_values[i].reset(new ::hp::FEValues<dim,spacedim>
174  (this->mapping_collection,
175  *this->finite_elements[i],
176  quadrature,
177  this->update_flags));
178  }
179  }
180  else
181  {
182  ::hp::QCollection<dim-1>
183  quadrature(QIterated<dim-1>(QTrapez<1>(), n_subdivisions));
184  x_fe_face_values.resize(this->finite_elements.size());
185  for (unsigned int i=0; i<this->finite_elements.size(); ++i)
186  {
187  // check if there is a finite element that is equal to the
188  // present one, then we can re-use the FEValues object
189  for (unsigned int j=0; j<i; ++j)
190  if (this->finite_elements[i].get() ==
191  this->finite_elements[j].get())
192  {
193  x_fe_face_values[i] = x_fe_face_values[j];
194  break;
195  }
196  if (x_fe_face_values[i].get() == 0)
197  x_fe_face_values[i].reset(new ::hp::FEFaceValues<dim,spacedim>
198  (this->mapping_collection,
199  *this->finite_elements[i],
200  quadrature,
201  this->update_flags));
202  }
203  }
204  }
205 
206 
207 
208  template <int dim, int spacedim>
209  template <typename DoFHandlerType>
210  void
211  ParallelDataBase<dim,spacedim>::
212  reinit_all_fe_values(std::vector<std_cxx11::shared_ptr<DataEntryBase<DoFHandlerType> > > &dof_data,
213  const typename ::Triangulation<dim,spacedim>::cell_iterator &cell,
214  const unsigned int face)
215  {
216  for (unsigned int dataset=0; dataset<dof_data.size(); ++dataset)
217  {
218  bool duplicate = false;
219  for (unsigned int j=0; j<dataset; ++j)
220  if (finite_elements[dataset].get() == finite_elements[j].get())
221  duplicate = true;
222  if (duplicate == false)
223  {
224  typename DoFHandlerType::active_cell_iterator dh_cell(&cell->get_triangulation(),
225  cell->level(),
226  cell->index(),
227  dof_data[dataset]->dof_handler);
228  if (x_fe_values.empty())
229  {
230  AssertIndexRange(face,
232  x_fe_face_values[dataset]->reinit(dh_cell, face);
233  }
234  else
235  x_fe_values[dataset]->reinit (dh_cell);
236  }
237  }
238  if (dof_data.empty())
239  {
240  if (x_fe_values.empty())
241  {
242  AssertIndexRange(face,
244  x_fe_face_values[0]->reinit(cell, face);
245  }
246  else
247  x_fe_values[0]->reinit (cell);
248  }
249  }
250 
251 
252 
253  template <int dim, int spacedim>
255  ParallelDataBase<dim,spacedim>::
256  get_present_fe_values(const unsigned int dataset) const
257  {
258  AssertIndexRange(dataset, finite_elements.size());
259  if (x_fe_values.empty())
260  return x_fe_face_values[dataset]->get_present_fe_values();
261  else
262  return x_fe_values[dataset]->get_present_fe_values();
263  }
264 
265 
266 
267  template <int dim, int spacedim>
268  void
269  ParallelDataBase<dim,spacedim>::
270  resize_system_vectors(const unsigned int n_components)
271  {
272  Assert(patch_values_system.size() > 0, ExcInternalError());
273  AssertDimension(patch_values_system.size(),
274  patch_gradients_system.size());
275  AssertDimension(patch_values_system.size(),
276  patch_hessians_system.size());
277  if (patch_values_system[0].size() == n_components)
278  return;
279  for (unsigned int k=0; k<patch_values_system.size(); ++k)
280  {
281  patch_values_system[k].reinit(n_components);
282  patch_gradients_system[k].resize(n_components);
283  patch_hessians_system[k].resize(n_components);
284  }
285  }
286 
287 
288 
289 
294  template <int dim, int spacedim>
295  void
296  append_patch_to_list (const DataOutBase::Patch<dim,spacedim> &patch,
298  {
299  patches.push_back (patch);
300  patches.back().patch_index = patches.size()-1;
301  }
302  }
303 }
304 
305 namespace internal
306 {
307  namespace DataOut
308  {
309  template <typename DoFHandlerType>
310  DataEntryBase<DoFHandlerType>::DataEntryBase
311  (const DoFHandlerType *dofs,
312  const std::vector<std::string> &names_in,
313  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
314  :
316  names(names_in),
317  data_component_interpretation (data_component_interpretation),
318  postprocessor(0, typeid(*this).name()),
319  n_output_variables(names.size())
320  {
321  Assert (names.size() == data_component_interpretation.size(),
322  ExcDimensionMismatch(data_component_interpretation.size(),
323  names.size()));
324 
325  // check that the names use only allowed characters
326  for (unsigned int i=0; i<names.size(); ++i)
327  Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
328  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
329  "0123456789_<>()") == std::string::npos,
330  Exceptions::DataOut::ExcInvalidCharacter (names[i],
331  names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
332  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
333  "0123456789_<>()")));
334  }
335 
336 
337 
338  template <typename DoFHandlerType>
340  (const DoFHandlerType *dofs,
341  const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor)
342  :
344  names(data_postprocessor->get_names()),
345  data_component_interpretation (data_postprocessor->get_data_component_interpretation()),
346  postprocessor(data_postprocessor, typeid(*this).name()),
347  n_output_variables(names.size())
348  {
349  Assert (data_postprocessor->get_names().size()
350  ==
351  data_postprocessor->get_data_component_interpretation().size(),
352  ExcDimensionMismatch (data_postprocessor->get_names().size(),
353  data_postprocessor->get_data_component_interpretation().size()));
354 
355  // check that the names use only allowed characters
356  for (unsigned int i=0; i<names.size(); ++i)
357  Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
358  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
359  "0123456789_<>()") == std::string::npos,
360  Exceptions::DataOut::ExcInvalidCharacter (names[i],
361  names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
362  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
363  "0123456789_<>()")));
364  }
365 
366 
367 
368  template <typename DoFHandlerType>
370  {}
371 
372 
373 
380  template <typename DoFHandlerType, typename VectorType>
381  class DataEntry : public DataEntryBase<DoFHandlerType>
382  {
383  public:
389  DataEntry
390  (const DoFHandlerType *dofs,
391  const VectorType *data,
392  const std::vector<std::string> &names,
393  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation);
394 
400  DataEntry (const DoFHandlerType *dofs,
401  const VectorType *data,
402  const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor);
403 
408  virtual
409  double
410  get_cell_data_value (const unsigned int cell_number) const;
411 
416  virtual
417  void
418  get_function_values
420  std::vector<double> &patch_values) const;
421 
427  virtual
428  void
429  get_function_values
431  std::vector<::Vector<double> > &patch_values_system) const;
432 
437  virtual
438  void
439  get_function_gradients
441  std::vector<Tensor<1,DoFHandlerType::space_dimension> > &patch_gradients) const;
442 
448  virtual
449  void
450  get_function_gradients
452  std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension> > > &patch_gradients_system) const;
453 
458  virtual
459  void
460  get_function_hessians
462  std::vector<Tensor<2,DoFHandlerType::space_dimension> > &patch_hessians) const;
463 
469  virtual
470  void
471  get_function_hessians
473  std::vector<std::vector< Tensor<2,DoFHandlerType::space_dimension> > > &patch_hessians_system) const;
474 
478  virtual void clear ();
479 
484  virtual std::size_t memory_consumption () const;
485 
486  private:
491  const VectorType *vector;
492  };
493 
494 
495 
496  template <typename DoFHandlerType, typename VectorType>
498  DataEntry (const DoFHandlerType *dofs,
499  const VectorType *data,
500  const std::vector<std::string> &names,
501  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
502  :
503  DataEntryBase<DoFHandlerType> (dofs, names, data_component_interpretation),
504  vector (data)
505  {}
506 
507 
508 
509  template <typename DoFHandlerType, typename VectorType>
511  DataEntry (const DoFHandlerType *dofs,
512  const VectorType *data,
513  const DataPostprocessor<DoFHandlerType::space_dimension> *data_postprocessor)
514  :
515  DataEntryBase<DoFHandlerType> (dofs, data_postprocessor),
516  vector (data)
517  {}
518 
519 
520  namespace
521  {
522  template <typename VectorType>
523  double
524  get_vector_element (const VectorType &vector,
525  const unsigned int cell_number)
526  {
527  return vector[cell_number];
528  }
529 
530 
531  double
532  get_vector_element (const IndexSet &is,
533  const unsigned int cell_number)
534  {
535  return (is.is_element(cell_number) ? 1 : 0);
536  }
537  }
538 
539 
540 
541  template <typename DoFHandlerType, typename VectorType>
542  double
544  get_cell_data_value (const unsigned int cell_number) const
545  {
546  return get_vector_element(*vector, cell_number);
547  }
548 
549 
550 
551  template <typename DoFHandlerType, typename VectorType>
552  void
555  std::vector<::Vector<double> > &patch_values_system) const
556  {
557  // FIXME: FEValuesBase gives us data in types that match that of
558  // the solution vector. but this function needs to pass it back
559  // up as 'double' vectors. this requires the use of a temporary
560  // variable here if the data we get is not a 'double' vector.
561  // (of course, in reality, this also means that we may lose
562  // information to begin with.)
563  //
564  // the correct thing would be to also use the correct data type
565  // upstream somewhere, but this is complicated because we hide
566  // the actual data type from upstream. rather, we should at
567  // least make sure we can deal with complex numbers
568  if (typeid(typename VectorType::value_type) == typeid(double))
569  {
570  fe_patch_values.get_function_values (*vector,
571  // reinterpret output argument type; because of
572  // the 'if' statement above, this is the
573  // identity cast whenever the code is
574  // executed, but the cast is necessary
575  // to allow compilation even if we don't get here
576  reinterpret_cast<std::vector<::Vector<typename VectorType::value_type> >&>
577  (patch_values_system));
578  }
579  else
580  {
581  std::vector<::Vector<typename VectorType::value_type> > tmp(patch_values_system.size());
582  for (unsigned int i = 0; i < patch_values_system.size(); i++)
583  tmp[i].reinit(patch_values_system[i]);
584 
585  fe_patch_values.get_function_values (*vector, tmp);
586 
587  for (unsigned int i = 0; i < patch_values_system.size(); i++)
588  patch_values_system[i] = tmp[i];
589  }
590  }
591 
592 
593 
594  template <typename DoFHandlerType, typename VectorType>
595  void
598  std::vector<double> &patch_values) const
599  {
600  // FIXME: FEValuesBase gives us data in types that match that of
601  // the solution vector. but this function needs to pass it back
602  // up as 'double' vectors. this requires the use of a temporary
603  // variable here if the data we get is not a 'double' vector.
604  // (of course, in reality, this also means that we may lose
605  // information to begin with.)
606  //
607  // the correct thing would be to also use the correct data type
608  // upstream somewhere, but this is complicated because we hide
609  // the actual data type from upstream. rather, we should at
610  // least make sure we can deal with complex numbers
611  if (typeid(typename VectorType::value_type) == typeid(double))
612  {
613  fe_patch_values.get_function_values (*vector,
614  // reinterpret output argument type; because of
615  // the 'if' statement above, this is the
616  // identity cast whenever the code is
617  // executed, but the cast is necessary
618  // to allow compilation even if we don't get here
619  reinterpret_cast<std::vector<typename VectorType::value_type>&>
620  (patch_values));
621  }
622  else
623  {
624  std::vector<typename VectorType::value_type> tmp (patch_values.size());
625 
626  fe_patch_values.get_function_values (*vector, tmp);
627 
628  for (unsigned int i = 0; i < tmp.size(); i++)
629  patch_values[i] = tmp[i];
630  }
631  }
632 
633 
634 
635  template <typename DoFHandlerType, typename VectorType>
636  void
639  std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension> > > &patch_gradients_system) const
640  {
641  // FIXME: FEValuesBase gives us data in types that match that of
642  // the solution vector. but this function needs to pass it back
643  // up as 'double' vectors. this requires the use of a temporary
644  // variable here if the data we get is not a 'double' vector.
645  // (of course, in reality, this also means that we may lose
646  // information to begin with.)
647  //
648  // the correct thing would be to also use the correct data type
649  // upstream somewhere, but this is complicated because we hide
650  // the actual data type from upstream. rather, we should at
651  // least make sure we can deal with complex numbers
652  if (typeid(typename VectorType::value_type) == typeid(double))
653  {
654  fe_patch_values.get_function_gradients (*vector,
655  // reinterpret output argument type; because of
656  // the 'if' statement above, this is the
657  // identity cast whenever the code is
658  // executed, but the cast is necessary
659  // to allow compilation even if we don't get here
660  reinterpret_cast<std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> > >&>
661  (patch_gradients_system));
662  }
663  else
664  {
665  std::vector<std::vector<Tensor<1,DoFHandlerType::space_dimension,
666  typename VectorType::value_type> > >
667  tmp(patch_gradients_system.size());
668  for (unsigned int i = 0; i < tmp.size(); i++)
669  tmp[i].resize(patch_gradients_system[i].size());
670 
671  fe_patch_values.get_function_gradients (*vector, tmp);
672 
673  for (unsigned int i = 0; i < tmp.size(); i++)
674  for (unsigned int j = 0; j < tmp[i].size(); j++)
675  patch_gradients_system[i][j] = tmp[i][j];
676  }
677  }
678 
679 
680 
681  template <typename DoFHandlerType, typename VectorType>
682  void
685  std::vector<Tensor<1,DoFHandlerType::space_dimension> > &patch_gradients) const
686  {
687  // FIXME: FEValuesBase gives us data in types that match that of
688  // the solution vector. but this function needs to pass it back
689  // up as 'double' vectors. this requires the use of a temporary
690  // variable here if the data we get is not a 'double' vector.
691  // (of course, in reality, this also means that we may lose
692  // information to begin with.)
693  //
694  // the correct thing would be to also use the correct data type
695  // upstream somewhere, but this is complicated because we hide
696  // the actual data type from upstream. rather, we should at
697  // least make sure we can deal with complex numbers
698  if (typeid(typename VectorType::value_type) == typeid(double))
699  {
700  fe_patch_values.get_function_gradients (*vector,
701  // reinterpret output argument type; because of
702  // the 'if' statement above, this is the
703  // identity cast whenever the code is
704  // executed, but the cast is necessary
705  // to allow compilation even if we don't get here
706  reinterpret_cast<std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> >&>
707  (patch_gradients));
708  }
709  else
710  {
711  std::vector<Tensor<1,DoFHandlerType::space_dimension,typename VectorType::value_type> > tmp;
712  tmp.resize(patch_gradients.size());
713 
714  fe_patch_values.get_function_gradients (*vector, tmp);
715 
716  for (unsigned int i = 0; i < tmp.size(); i++)
717  patch_gradients[i] = tmp[i];
718  }
719  }
720 
721 
722 
723  template <typename DoFHandlerType, typename VectorType>
724  void
727  std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension> > > &patch_hessians_system) const
728  {
729  // FIXME: FEValuesBase gives us data in types that match that of
730  // the solution vector. but this function needs to pass it back
731  // up as 'double' vectors. this requires the use of a temporary
732  // variable here if the data we get is not a 'double' vector.
733  // (of course, in reality, this also means that we may lose
734  // information to begin with.)
735  //
736  // the correct thing would be to also use the correct data type
737  // upstream somewhere, but this is complicated because we hide
738  // the actual data type from upstream. rather, we should at
739  // least make sure we can deal with complex numbers
740  if (typeid(typename VectorType::value_type) == typeid(double))
741  {
742  fe_patch_values.get_function_hessians (*vector,
743  // reinterpret output argument type; because of
744  // the 'if' statement above, this is the
745  // identity cast whenever the code is
746  // executed, but the cast is necessary
747  // to allow compilation even if we don't get here
748  reinterpret_cast<std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension,typename VectorType::value_type> > >&>
749  (patch_hessians_system));
750  }
751  else
752  {
753  std::vector<std::vector<Tensor<2,DoFHandlerType::space_dimension,
754  typename VectorType::value_type> > >
755  tmp(patch_hessians_system.size());
756  for (unsigned int i = 0; i < tmp.size(); i++)
757  tmp[i].resize(patch_hessians_system[i].size());
758 
759  fe_patch_values.get_function_hessians (*vector, tmp);
760 
761  for (unsigned int i = 0; i < tmp.size(); i++)
762  for (unsigned int j = 0; j < tmp[i].size(); j++)
763  patch_hessians_system[i][j] = tmp[i][j];
764  }
765  }
766 
767 
768 
769  template <typename DoFHandlerType, typename VectorType>
770  void
773  std::vector<Tensor<2,DoFHandlerType::space_dimension> > &patch_hessians) const
774  {
775  // FIXME: FEValuesBase gives us data in types that match that of
776  // the solution vector. but this function needs to pass it back
777  // up as 'double' vectors. this requires the use of a temporary
778  // variable here if the data we get is not a 'double' vector.
779  // (of course, in reality, this also means that we may lose
780  // information to begin with.)
781  //
782  // the correct thing would be to also use the correct data type
783  // upstream somewhere, but this is complicated because we hide
784  // the actual data type from upstream. rather, we should at
785  // least make sure we can deal with complex numbers
786  if (typeid(typename VectorType::value_type) == typeid(double))
787  {
788  fe_patch_values.get_function_hessians (*vector,
789  // reinterpret output argument type; because of
790  // the 'if' statement above, this is the
791  // identity cast whenever the code is
792  // executed, but the cast is necessary
793  // to allow compilation even if we don't get here
794  reinterpret_cast<std::vector<Tensor<2,DoFHandlerType
795  ::space_dimension,typename VectorType::value_type> >&>
796  (patch_hessians));
797  }
798  else
799  {
800  std::vector<Tensor<2,DoFHandlerType::space_dimension,typename VectorType::value_type> >
801  tmp(patch_hessians.size());
802 
803  fe_patch_values.get_function_hessians (*vector, tmp);
804 
805  for (unsigned int i = 0; i < tmp.size(); i++)
806  patch_hessians[i] = tmp[i];
807  }
808  }
809 
810 
811 
812  template <typename DoFHandlerType, typename VectorType>
813  std::size_t
815  {
816  return (sizeof (vector) +
818  }
819 
820 
821 
822  template <typename DoFHandlerType, typename VectorType>
823  void
825  {
826  vector = 0;
827  this->dof_handler = 0;
828  }
829  }
830 }
831 
832 
833 
834 template <typename DoFHandlerType,
835  int patch_dim, int patch_space_dim>
837  :
838  triangulation(0,typeid(*this).name()),
839  dofs(0,typeid(*this).name())
840 {}
841 
842 
843 
844 template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
846 {
847  clear ();
848 }
849 
850 
851 
852 template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
853 void
855 attach_dof_handler (const DoFHandlerType &d)
856 {
857  Assert (dof_data.size() == 0,
858  Exceptions::DataOut::ExcOldDataStillPresent());
859  Assert (cell_data.size() == 0,
860  Exceptions::DataOut::ExcOldDataStillPresent());
861 
862  triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,
863  DoFHandlerType::space_dimension> >
864  (&d.get_triangulation(), typeid(*this).name());
865  dofs = SmartPointer<const DoFHandlerType>(&d, typeid(*this).name());
866 }
867 
868 
869 
870 template <typename DoFHandlerType, int patch_dim, int patch_space_dim>
871 void
874 {
875  Assert (dof_data.size() == 0,
876  Exceptions::DataOut::ExcOldDataStillPresent());
877  Assert (cell_data.size() == 0,
878  Exceptions::DataOut::ExcOldDataStillPresent());
879 
880  triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,
881  DoFHandlerType::space_dimension> >
882  (&tria, typeid(*this).name());
883 }
884 
885 
886 
887 
888 template <typename DoFHandlerType,
889  int patch_dim, int patch_space_dim>
890 template <typename VectorType>
891 void
893 add_data_vector (const VectorType &vec,
894  const std::string &name,
895  const DataVectorType type,
896  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
897 {
898  Assert (triangulation != 0,
899  Exceptions::DataOut::ExcNoTriangulationSelected ());
900  const unsigned int n_components =
901  dofs != 0 ? dofs->get_fe().n_components () : 1;
902 
903  std::vector<std::string> names;
904  // if only one component or vector is cell vector: we only need one name
905  if ((n_components == 1) ||
906  (vec.size() == triangulation->n_active_cells()))
907  {
908  names.resize (1, name);
909  }
910  else
911  // otherwise append _i to the given name
912  {
913  names.resize (n_components);
914  for (unsigned int i=0; i<n_components; ++i)
915  {
916  std::ostringstream namebuf;
917  namebuf << '_' << i;
918  names[i] = name + namebuf.str();
919  }
920  }
921 
922  add_data_vector (vec, names, type, data_component_interpretation);
923 }
924 
925 
926 
927 template <typename DoFHandlerType,
928  int patch_dim, int patch_space_dim>
929 template <typename VectorType>
930 void
932 add_data_vector (const VectorType &vec,
933  const std::vector<std::string> &names,
934  const DataVectorType type,
935  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation_)
936 {
937  Assert (triangulation != 0,
938  Exceptions::DataOut::ExcNoTriangulationSelected ());
939 
940  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &
941  data_component_interpretation
942  = (data_component_interpretation_.size() != 0
943  ?
944  data_component_interpretation_
945  :
946  std::vector<DataComponentInterpretation::DataComponentInterpretation>
948 
949  // either cell data and one name,
950  // or dof data and n_components names
951  DataVectorType actual_type = type;
952  if (type == type_automatic)
953  {
954  // in the rare case that someone has a DGP(0) attached, we can not decide what she wants here:
955  Assert((dofs == 0) || (triangulation->n_active_cells() != dofs->n_dofs()),
956  ExcMessage("Unable to determine the type of vector automatically because the number of DoFs "
957  "is equal to the number of cells. Please specify DataVectorType."));
958 
959  if (vec.size() == triangulation->n_active_cells())
960  actual_type = type_cell_data;
961  else
962  actual_type = type_dof_data;
963  }
964 
965  switch (actual_type)
966  {
967  case type_cell_data:
968  Assert (vec.size() == triangulation->n_active_cells(),
969  ExcDimensionMismatch (vec.size(),
971  Assert (names.size() == 1,
972  Exceptions::DataOut::ExcInvalidNumberOfNames (names.size(), 1));
973  break;
974 
975  case type_dof_data:
976  Assert (dofs != 0,
977  Exceptions::DataOut::ExcNoDoFHandlerSelected ());
978  Assert (vec.size() == dofs->n_dofs(),
979  Exceptions::DataOut::ExcInvalidVectorSize (vec.size(),
980  dofs->n_dofs(),
982  Assert (names.size() == dofs->get_fe().n_components(),
983  Exceptions::DataOut::ExcInvalidNumberOfNames (names.size(),
984  dofs->get_fe().n_components()));
985  break;
986 
987  case type_automatic:
988  // this case should have been handled above...
989  Assert (false, ExcInternalError());
990  }
991 
994  data_component_interpretation);
995  if (actual_type == type_dof_data)
996  dof_data.push_back (std_cxx11::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> >(new_entry));
997  else
998  cell_data.push_back (std_cxx11::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> >(new_entry));
999 }
1000 
1001 
1002 
1003 template <typename DoFHandlerType,
1004  int patch_dim, int patch_space_dim>
1005 template <typename VectorType>
1006 void
1008 add_data_vector (const VectorType &vec,
1009  const DataPostprocessor<DoFHandlerType::space_dimension> &data_postprocessor)
1010 {
1011  // this is a specialized version of the other function where we have a
1012  // postprocessor. if we do, we know that we have type_dof_data, which makes
1013  // things a bit simpler, we also don't need to deal with some of the other
1014  // stuff and use a different constructor of DataEntry
1015 
1016  Assert (dofs != 0,
1017  Exceptions::DataOut::ExcNoDoFHandlerSelected ());
1018 
1019  Assert (vec.size() == dofs->n_dofs(),
1020  Exceptions::DataOut::ExcInvalidVectorSize (vec.size(),
1021  dofs->n_dofs(),
1022  dofs->get_triangulation().n_active_cells()));
1023 
1025  = new internal::DataOut::DataEntry<DoFHandlerType,VectorType>(dofs, &vec, &data_postprocessor);
1026  dof_data.push_back (std_cxx11::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> >(new_entry));
1027 }
1028 
1029 
1030 
1031 template <typename DoFHandlerType,
1032  int patch_dim, int patch_space_dim>
1033 template <typename VectorType>
1034 void
1036 add_data_vector (const DoFHandlerType &dof_handler,
1037  const VectorType &vec,
1038  const DataPostprocessor<DoFHandlerType::space_dimension> &data_postprocessor)
1039 {
1040  // this is a specialized version of the other function where we have a
1041  // postprocessor. if we do, we know that we have type_dof_data, which makes
1042  // things a bit simpler, we also don't need to deal with some of the other
1043  // stuff and use a different constructor of DataEntry
1044 
1045  AssertDimension (vec.size(), dof_handler.n_dofs());
1046 
1048  = new internal::DataOut::DataEntry<DoFHandlerType,VectorType>(&dof_handler, &vec, &data_postprocessor);
1049  dof_data.push_back (std_cxx11::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> >(new_entry));
1050 }
1051 
1052 
1053 
1054 template <typename DoFHandlerType,
1055  int patch_dim, int patch_space_dim>
1056 template <typename VectorType>
1057 void
1060 (const DoFHandlerType &dof_handler,
1061  const VectorType &data,
1062  const std::string &name,
1063  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation)
1064 {
1065  const unsigned int n_components = dof_handler.get_fe().n_components ();
1066 
1067  std::vector<std::string> names;
1068  // if only one component: we only need one name
1069  if (n_components == 1)
1070  names.resize (1, name);
1071  else
1072  // otherwise append _i to the given name
1073  {
1074  names.resize (n_components);
1075  for (unsigned int i=0; i<n_components; ++i)
1076  {
1077  std::ostringstream namebuf;
1078  namebuf << '_' << i;
1079  names[i] = name + namebuf.str();
1080  }
1081  }
1082 
1083  add_data_vector (dof_handler, data, names, data_component_interpretation);
1084 }
1085 
1086 
1087 
1088 template <typename DoFHandlerType,
1089  int patch_dim, int patch_space_dim>
1090 template <typename VectorType>
1091 void
1094 (const DoFHandlerType &dof_handler,
1095  const VectorType &data,
1096  const std::vector<std::string> &names,
1097  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &data_component_interpretation_)
1098 {
1099  // this is an extended version of the other functions where we pass a vector
1100  // together with its DoFHandler. if we do, we know that we have
1101  // type_dof_data, which makes things a bit simpler
1102  if (triangulation == 0)
1103  triangulation = SmartPointer<const Triangulation<DoFHandlerType::dimension,DoFHandlerType::space_dimension> >(&dof_handler.get_triangulation(), typeid(*this).name());
1104 
1105  Assert (&dof_handler.get_triangulation() == triangulation,
1106  ExcMessage("The triangulation attached to the DoFHandler does not "
1107  "match with the one set previously"));
1108 
1109  Assert (data.size() == dof_handler.n_dofs(),
1110  ExcDimensionMismatch (data.size(), dof_handler.n_dofs()));
1111 
1112  const std::vector<DataComponentInterpretation::DataComponentInterpretation> &
1113  data_component_interpretation
1114  = (data_component_interpretation_.size() != 0
1115  ?
1116  data_component_interpretation_
1117  :
1118  std::vector<DataComponentInterpretation::DataComponentInterpretation>
1120 
1122  = new internal::DataOut::DataEntry<DoFHandlerType,VectorType>(&dof_handler, &data, names,
1123  data_component_interpretation);
1124  dof_data.push_back (std_cxx11::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> >(new_entry));
1125 }
1126 
1127 
1128 
1129 template <typename DoFHandlerType,
1130  int patch_dim, int patch_space_dim>
1132 {
1133  dof_data.erase (dof_data.begin(), dof_data.end());
1134  cell_data.erase (cell_data.begin(), cell_data.end());
1135 
1136  // delete patches
1137  std::vector<Patch> dummy;
1138  patches.swap (dummy);
1139 }
1140 
1141 
1142 
1143 template <typename DoFHandlerType,
1144  int patch_dim, int patch_space_dim>
1145 void
1148 {
1149  for (unsigned int i=0; i<dof_data.size(); ++i)
1150  dof_data[i]->clear ();
1151 
1152  for (unsigned int i=0; i<cell_data.size(); ++i)
1153  cell_data[i]->clear ();
1154 
1155  if (dofs != 0)
1156  dofs = 0;
1157 }
1158 
1159 
1160 
1161 template <typename DoFHandlerType,
1162  int patch_dim, int patch_space_dim>
1163 void
1165 {
1166  dof_data.erase (dof_data.begin(), dof_data.end());
1167  cell_data.erase (cell_data.begin(), cell_data.end());
1168 
1169  if (dofs != 0)
1170  dofs = 0;
1171 
1172  // delete patches
1173  std::vector<Patch> dummy;
1174  patches.swap (dummy);
1175 }
1176 
1177 
1178 
1179 template <typename DoFHandlerType,
1180  int patch_dim, int patch_space_dim>
1181 std::vector<std::string>
1184 {
1185  std::vector<std::string> names;
1186  // collect the names of dof
1187  // and cell data
1188  typedef
1189  typename std::vector<std_cxx11::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> > >::const_iterator
1190  data_iterator;
1191 
1192  for (data_iterator d=dof_data.begin();
1193  d!=dof_data.end(); ++d)
1194  for (unsigned int i=0; i<(*d)->names.size(); ++i)
1195  names.push_back ((*d)->names[i]);
1196  for (data_iterator d=cell_data.begin(); d!=cell_data.end(); ++d)
1197  {
1198  Assert ((*d)->names.size() == 1, ExcInternalError());
1199  names.push_back ((*d)->names[0]);
1200  }
1201 
1202  return names;
1203 }
1204 
1205 
1206 
1207 template <typename DoFHandlerType,
1208  int patch_dim, int patch_space_dim>
1209 std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> >
1211 {
1212  std::vector<std_cxx11::tuple<unsigned int, unsigned int, std::string> >
1213  ranges;
1214 
1215  // collect the ranges of dof
1216  // and cell data
1217  typedef
1218  typename std::vector<std_cxx11::shared_ptr<internal::DataOut::DataEntryBase<DoFHandlerType> > >::const_iterator
1219  data_iterator;
1220 
1221  unsigned int output_component = 0;
1222  for (data_iterator d=dof_data.begin();
1223  d!=dof_data.end(); ++d)
1224  for (unsigned int i=0; i<(*d)->n_output_variables;
1225  ++i, ++output_component)
1226  // see what kind of data we have
1227  // here. note that for the purpose of
1228  // the current function all we care
1229  // about is vector data
1230  if ((*d)->data_component_interpretation[i] ==
1232  {
1233  // ensure that there is a
1234  // continuous number of next
1235  // space_dim components that all
1236  // deal with vectors
1237  Assert (i+patch_space_dim <=
1238  (*d)->n_output_variables,
1239  Exceptions::DataOut::ExcInvalidVectorDeclaration (i,
1240  (*d)->names[i]));
1241  for (unsigned int dd=1; dd<patch_space_dim; ++dd)
1242  Assert ((*d)->data_component_interpretation[i+dd]
1243  ==
1245  Exceptions::DataOut::ExcInvalidVectorDeclaration (i,
1246  (*d)->names[i]));
1247 
1248  // all seems alright, so figure out
1249  // whether there is a common name
1250  // to these components. if not,
1251  // leave the name empty and let the
1252  // output format writer decide what
1253  // to do here
1254  std::string name = (*d)->names[i];
1255  for (unsigned int dd=1; dd<patch_space_dim; ++dd)
1256  if (name != (*d)->names[i+dd])
1257  {
1258  name = "";
1259  break;
1260  }
1261 
1262  // finally add a corresponding
1263  // range
1264  std_cxx11::tuple<unsigned int, unsigned int, std::string>
1265  range (output_component,
1266  output_component+patch_space_dim-1,
1267  name);
1268 
1269  ranges.push_back (range);
1270 
1271  // increase the 'component' counter
1272  // by the appropriate amount, same
1273  // for 'i', since we have already
1274  // dealt with all these components
1275  output_component += patch_space_dim-1;
1276  i += patch_space_dim-1;
1277  }
1278 
1279  // note that we do not have to traverse the
1280  // list of cell data here because cell data
1281  // is one value per (logical) cell and
1282  // therefore cannot be a vector
1283 
1284  // as a final check, the 'component'
1285  // counter should be at the total number of
1286  // components added up now
1287 #ifdef DEBUG
1288  unsigned int n_output_components = 0;
1289  for (data_iterator d=dof_data.begin();
1290  d!=dof_data.end(); ++d)
1291  n_output_components += (*d)->n_output_variables;
1292  Assert (output_component == n_output_components,
1293  ExcInternalError());
1294 #endif
1295 
1296  return ranges;
1297 }
1298 
1299 
1300 
1301 template <typename DoFHandlerType,
1302  int patch_dim, int patch_space_dim>
1303 const std::vector< ::DataOutBase::Patch<patch_dim, patch_space_dim> > &
1305 {
1306  return patches;
1307 }
1308 
1309 
1310 
1311 template <typename DoFHandlerType,
1312  int patch_dim, int patch_space_dim>
1313 std::vector<std_cxx11::shared_ptr<::hp::FECollection<DoFHandlerType::dimension,
1314  DoFHandlerType::space_dimension> > >
1316 {
1317  const unsigned int dhdim = DoFHandlerType::dimension;
1318  const unsigned int dhspacedim = DoFHandlerType::space_dimension;
1319  std::vector<std_cxx11::shared_ptr<::hp::FECollection<dhdim,dhspacedim> > >
1320  finite_elements(this->dof_data.size());
1321  for (unsigned int i=0; i<this->dof_data.size(); ++i)
1322  {
1323  Assert (dof_data[i]->dof_handler != 0,
1324  Exceptions::DataOut::ExcNoDoFHandlerSelected ());
1325 
1326  // avoid creating too many finite elements and doing a lot of work on
1327  // initializing FEValues downstream: if two DoFHandlers are the same
1328  // (checked by pointer comparison), we can re-use the shared_ptr object
1329  // for the second one. We cannot check for finite element equalities
1330  // because we need different FEValues objects for different dof
1331  // handlers.
1332  bool duplicate = false;
1333  for (unsigned int j=0; j<i; ++j)
1334  if (dof_data[i]->dof_handler == dof_data[j]->dof_handler)
1335  {
1336  finite_elements[i] = finite_elements[j];
1337  duplicate = true;
1338  }
1339  if (duplicate == false)
1340  finite_elements[i].reset(new ::hp::FECollection<dhdim,dhspacedim>
1341  (this->dof_data[i]->dof_handler->get_fe()));
1342  }
1343  if (this->dof_data.empty())
1344  {
1345  finite_elements.resize(1);
1346  finite_elements[0].reset(new ::hp::FECollection<dhdim,dhspacedim>
1348  }
1349  return finite_elements;
1350 }
1351 
1352 
1353 
1354 template <typename DoFHandlerType,
1355  int patch_dim, int patch_space_dim>
1356 std::size_t
1358 {
1362 }
1363 
1364 
1365 
1366 // explicit instantiations
1367 #include "data_out_dof_data.inst"
1368 
1369 DEAL_II_NAMESPACE_CLOSE
std::vector< std_cxx11::shared_ptr< internal::DataOut::DataEntryBase< DoFHandlerType > > > cell_data
void get_function_gradients(const InputVector &fe_function, std::vector< Tensor< 1, spacedim, typename InputVector::value_type > > &gradients) const
Definition: fe_values.cc:2871
unsigned int n_active_cells() const
Definition: tria.cc:10973
void clear_input_data_references()
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1052
void attach_triangulation(const Triangulation< DoFHandlerType::dimension, DoFHandlerType::space_dimension > &)
Definition: fe_dgq.h:81
::ExceptionBase & ExcMessage(std::string arg1)
#define AssertIndexRange(index, range)
Definition: exceptions.h:1081
void get_function_values(const InputVector &fe_function, std::vector< typename InputVector::value_type > &values) const
Definition: fe_values.cc:2710
void attach_dof_handler(const DoFHandlerType &)
virtual std::vector< std_cxx11::tuple< unsigned int, unsigned int, std::string > > get_vector_data_ranges() const
void get_function_hessians(const InputVector &fe_function, std::vector< Tensor< 2, spacedim, typename InputVector::value_type > > &hessians) const
Definition: fe_values.cc:2994
virtual std::size_t memory_consumption() const
#define Assert(cond, exc)
Definition: exceptions.h:294
UpdateFlags
virtual ~DataOut_DoFData()
Abstract base class for mapping classes.
Definition: dof_tools.h:52
SmartPointer< const DoFHandlerType > dof_handler
void add_data_vector(const VectorType &data, const std::vector< std::string > &names, const DataVectorType type=type_automatic, const std::vector< DataComponentInterpretation::DataComponentInterpretation > &data_component_interpretation=std::vector< DataComponentInterpretation::DataComponentInterpretation >())
DataEntry(const DoFHandlerType *dofs, const VectorType *data, const std::vector< std::string > &names, const std::vector< DataComponentInterpretation::DataComponentInterpretation > &data_component_interpretation)
virtual std::vector< std::string > get_dataset_names() const
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
virtual double get_cell_data_value(const unsigned int cell_number) const
virtual void get_function_hessians(const FEValuesBase< DoFHandlerType::dimension, DoFHandlerType::space_dimension > &fe_patch_values, std::vector< Tensor< 2, DoFHandlerType::space_dimension > > &patch_hessians) const
std::vector< std_cxx11::shared_ptr<::hp::FECollection< DoFHandlerType::dimension, DoFHandlerType::space_dimension > > > get_finite_elements() const
Definition: mpi.h:48
virtual void get_function_gradients(const FEValuesBase< DoFHandlerType::dimension, DoFHandlerType::space_dimension > &fe_patch_values, std::vector< Tensor< 1, DoFHandlerType::space_dimension > > &patch_gradients) const
SmartPointer< const Triangulation< DoFHandlerType::dimension, DoFHandlerType::space_dimension > > triangulation
virtual std::vector< DataComponentInterpretation::DataComponentInterpretation > get_data_component_interpretation() const
std::vector< std_cxx11::shared_ptr< internal::DataOut::DataEntryBase< DoFHandlerType > > > dof_data
bool is_element(const size_type index) const
Definition: index_set.h:1317
virtual void get_function_values(const FEValuesBase< DoFHandlerType::dimension, DoFHandlerType::space_dimension > &fe_patch_values, std::vector< double > &patch_values) const
const std::vector< std::string > names
virtual std::vector< std::string > get_names() const =0
virtual const std::vector< Patch > & get_patches() const