Reference documentation for deal.II version 8.5.1
data_out_faces.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2016 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/lac/vector.h>
19 #include <deal.II/lac/block_vector.h>
20 #include <deal.II/numerics/data_out_faces.h>
21 #include <deal.II/grid/tria.h>
22 #include <deal.II/dofs/dof_handler.h>
23 #include <deal.II/dofs/dof_accessor.h>
24 #include <deal.II/grid/tria_iterator.h>
25 #include <deal.II/fe/fe.h>
26 #include <deal.II/fe/fe_values.h>
27 #include <deal.II/hp/fe_values.h>
28 #include <deal.II/fe/mapping_q1.h>
29 
30 DEAL_II_NAMESPACE_OPEN
31 
32 
33 namespace internal
34 {
35  namespace DataOutFaces
36  {
37  template <int dim, int spacedim>
38  ParallelData<dim,spacedim>::
39  ParallelData (const unsigned int n_datasets,
40  const unsigned int n_subdivisions,
41  const std::vector<unsigned int> &n_postprocessor_outputs,
42  const Mapping<dim,spacedim> &mapping,
43  const std::vector<std_cxx11::shared_ptr<::hp::FECollection<dim,spacedim> > > &finite_elements,
44  const UpdateFlags update_flags)
45  :
46  internal::DataOut::
47  ParallelDataBase<dim,spacedim> (n_datasets,
48  n_subdivisions,
49  n_postprocessor_outputs,
50  mapping,
51  finite_elements,
52  update_flags,
53  true)
54  {}
55 
56 
57 
62  template <int dim, int spacedim>
63  void
64  append_patch_to_list (const DataOutBase::Patch<dim-1,spacedim> &patch,
65  std::vector<DataOutBase::Patch<dim-1,spacedim> > &patches)
66  {
67  patches.push_back (patch);
68  patches.back().patch_index = patches.size()-1;
69  }
70  }
71 }
72 
73 
74 
75 template <int dim, typename DoFHandlerType>
77  :
78  surface_only(so)
79 {
80  Assert (dim == DoFHandlerType::dimension,
82 }
83 
84 
85 
86 template <int dim, typename DoFHandlerType>
87 void
89 build_one_patch (const FaceDescriptor *cell_and_face,
92 {
93  Assert (cell_and_face->first->is_locally_owned(),
95 
96  // we use the mapping to transform the vertices. However, the mapping works
97  // on cells, not faces, so transform the face vertex to a cell vertex, that
98  // to a unit cell vertex and then, finally, that to the mapped vertex. In
99  // most cases this complicated procedure will be the identity.
100  for (unsigned int vertex=0; vertex<GeometryInfo<dimension-1>::vertices_per_cell; ++vertex)
101  patch.vertices[vertex] = data.mapping_collection[0].transform_unit_to_real_cell
102  (cell_and_face->first,
105  (cell_and_face->second,
106  vertex,
107  cell_and_face->first->face_orientation(cell_and_face->second),
108  cell_and_face->first->face_flip(cell_and_face->second),
109  cell_and_face->first->face_rotation(cell_and_face->second))));
110 
111  if (data.n_datasets > 0)
112  {
113  data.reinit_all_fe_values(this->dof_data, cell_and_face->first,
114  cell_and_face->second);
115  const FEValuesBase<dimension> &fe_patch_values
116  = data.get_present_fe_values (0);
117 
118  const unsigned int n_q_points = fe_patch_values.n_quadrature_points;
119 
120  // store the intermediate points
121  Assert(patch.space_dim==dimension, ExcInternalError());
122  const std::vector<Point<dimension> > &q_points=fe_patch_values.get_quadrature_points();
123  // resize the patch.data member in order to have enough memory for the
124  // quadrature points as well
125  patch.data.reinit(data.n_datasets+dimension,
126  patch.data.size(1));
127  // set the flag indicating that for this cell the points are explicitly
128  // given
129  patch.points_are_available=true;
130  // copy points to patch.data
131  for (unsigned int i=0; i<dimension; ++i)
132  for (unsigned int q=0; q<n_q_points; ++q)
133  patch.data(patch.data.size(0)-dimension+i,q)=q_points[q][i];
134 
135  // counter for data records
136  unsigned int offset=0;
137 
138  // first fill dof_data
139  for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
140  {
141  const FEValuesBase<dimension> &this_fe_patch_values
142  = data.get_present_fe_values (dataset);
143  const unsigned int n_components
144  = this_fe_patch_values.get_fe().n_components();
145  const DataPostprocessor<dim> *postprocessor=this->dof_data[dataset]->postprocessor;
146  if (postprocessor != 0)
147  {
148  // we have to postprocess the data, so determine, which fields
149  // have to be updated
150  const UpdateFlags update_flags=postprocessor->get_needed_update_flags();
151 
152  if (n_components == 1)
153  {
154  // at each point there is only one component of value,
155  // gradient etc.
156  if (update_flags & update_values)
157  this->dof_data[dataset]->get_function_values (this_fe_patch_values,
158  data.patch_values_scalar.solution_values);
159  if (update_flags & update_gradients)
160  this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
161  data.patch_values_scalar.solution_gradients);
162  if (update_flags & update_hessians)
163  this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
164  data.patch_values_scalar.solution_hessians);
165 
166  if (update_flags & update_quadrature_points)
167  data.patch_values_scalar.evaluation_points = this_fe_patch_values.get_quadrature_points();
168 
169  if (update_flags & update_normal_vectors)
170  data.patch_values_scalar.normals = this_fe_patch_values.get_all_normal_vectors();
171 
172  const typename DoFHandlerType::active_cell_iterator dh_cell(&cell_and_face->first->get_triangulation(),
173  cell_and_face->first->level(),
174  cell_and_face->first->index(),
175  this->dof_data[dataset]->dof_handler);
176  data.patch_values_scalar.template set_cell<DoFHandlerType> (dh_cell);
177 
178  postprocessor->
179  evaluate_scalar_field(data.patch_values_scalar,
180  data.postprocessed_values[dataset]);
181  }
182  else
183  {
184  // at each point there is a vector valued function and its
185  // derivative...
186  data.resize_system_vectors(n_components);
187  if (update_flags & update_values)
188  this->dof_data[dataset]->get_function_values (this_fe_patch_values,
189  data.patch_values_system.solution_values);
190  if (update_flags & update_gradients)
191  this->dof_data[dataset]->get_function_gradients (this_fe_patch_values,
192  data.patch_values_system.solution_gradients);
193  if (update_flags & update_hessians)
194  this->dof_data[dataset]->get_function_hessians (this_fe_patch_values,
195  data.patch_values_system.solution_hessians);
196 
197  if (update_flags & update_quadrature_points)
198  data.patch_values_system.evaluation_points = this_fe_patch_values.get_quadrature_points();
199 
200  if (update_flags & update_normal_vectors)
201  data.patch_values_system.normals = this_fe_patch_values.get_all_normal_vectors();
202 
203  const typename DoFHandlerType::active_cell_iterator dh_cell(&cell_and_face->first->get_triangulation(),
204  cell_and_face->first->level(),
205  cell_and_face->first->index(),
206  this->dof_data[dataset]->dof_handler);
207  data.patch_values_system.template set_cell<DoFHandlerType> (dh_cell);
208 
209  postprocessor->
210  evaluate_vector_field(data.patch_values_system,
211  data.postprocessed_values[dataset]);
212  }
213 
214  for (unsigned int q=0; q<n_q_points; ++q)
215  for (unsigned int component=0;
216  component<this->dof_data[dataset]->n_output_variables; ++component)
217  patch.data(offset+component,q)
218  = data.postprocessed_values[dataset][q](component);
219  }
220  else
221  // now we use the given data vector without modifications. again,
222  // we treat single component functions separately for efficiency
223  // reasons.
224  if (n_components == 1)
225  {
226  this->dof_data[dataset]->get_function_values (this_fe_patch_values,
227  data.patch_values_scalar.solution_values);
228  for (unsigned int q=0; q<n_q_points; ++q)
229  patch.data(offset,q) = data.patch_values_scalar.solution_values[q];
230  }
231  else
232  {
233  data.resize_system_vectors(n_components);
234  this->dof_data[dataset]->get_function_values (this_fe_patch_values,
235  data.patch_values_system.solution_values);
236  for (unsigned int component=0; component<n_components;
237  ++component)
238  for (unsigned int q=0; q<n_q_points; ++q)
239  patch.data(offset+component,q) =
240  data.patch_values_system.solution_values[q](component);
241  }
242  // increment the counter for the actual data record
243  offset += this->dof_data[dataset]->n_output_variables;
244  }
245 
246  // then do the cell data
247  for (unsigned int dataset=0; dataset<this->cell_data.size(); ++dataset)
248  {
249  // we need to get at the number of the cell to which this face
250  // belongs in order to access the cell data. this is not readily
251  // available, so choose the following rather inefficient way:
252  Assert (cell_and_face->first->active(),
253  ExcMessage("The current function is trying to generate cell-data output "
254  "for a face that does not belong to an active cell. This is "
255  "not supported."));
256  const unsigned int cell_number
257  = std::distance (this->triangulation->begin_active(),
259 
260  const double value
261  = this->cell_data[dataset]->get_cell_data_value (cell_number);
262  for (unsigned int q=0; q<n_q_points; ++q)
263  patch.data(dataset+offset,q) = value;
264  }
265  }
266 }
267 
268 
269 
270 
271 template <int dim, typename DoFHandlerType>
272 void DataOutFaces<dim,DoFHandlerType>::build_patches (const unsigned int n_subdivisions_)
273 {
274  build_patches (StaticMappingQ1<dimension>::mapping, n_subdivisions_);
275 }
276 
277 
278 
279 template <int dim, typename DoFHandlerType>
281  const unsigned int n_subdivisions_)
282 {
283  // Check consistency of redundant template parameter
284  Assert (dim==dimension, ExcDimensionMismatch(dim, dimension));
285 
286  const unsigned int n_subdivisions = (n_subdivisions_ != 0)
287  ? n_subdivisions_
288  : this->default_subdivisions;
289 
290  Assert (n_subdivisions >= 1,
292 
293  Assert (this->triangulation != 0,
295 
296  this->validate_dataset_names();
297 
298  unsigned int n_datasets = this->cell_data.size();
299  for (unsigned int i=0; i<this->dof_data.size(); ++i)
300  n_datasets += this->dof_data[i]->n_output_variables;
301 
302  // first collect the cells we want to create patches of; we will
303  // then iterate over them. the end-condition of the loop needs to
304  // test that next_face() returns an end iterator, as well as for the
305  // case that first_face() returns an invalid FaceDescriptor object
306  std::vector<FaceDescriptor> all_faces;
307  for (FaceDescriptor face=first_face();
308  ((face.first != this->triangulation->end())
309  &&
310  (face != FaceDescriptor()));
311  face = next_face(face))
312  all_faces.push_back (face);
313 
314  // clear the patches array and allocate the right number of elements
315  this->patches.clear ();
316  this->patches.reserve (all_faces.size());
317  Assert (this->patches.size() == 0, ExcInternalError());
318 
319 
320  std::vector<unsigned int> n_postprocessor_outputs (this->dof_data.size());
321  for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
322  if (this->dof_data[dataset]->postprocessor)
323  n_postprocessor_outputs[dataset] = this->dof_data[dataset]->n_output_variables;
324  else
325  n_postprocessor_outputs[dataset] = 0;
326 
327  UpdateFlags update_flags=update_values;
328  for (unsigned int i=0; i<this->dof_data.size(); ++i)
329  if (this->dof_data[i]->postprocessor)
330  update_flags |= this->dof_data[i]->postprocessor->get_needed_update_flags();
331  update_flags |= update_quadrature_points;
332 
334  thread_data (n_datasets,
335  n_subdivisions,
336  n_postprocessor_outputs,
337  mapping,
338  this->get_finite_elements(),
339  update_flags);
340  DataOutBase::Patch<dimension-1,space_dimension> sample_patch;
341  sample_patch.n_subdivisions = n_subdivisions;
342  sample_patch.data.reinit (n_datasets,
343  Utilities::fixed_power<dimension-1>(n_subdivisions+1));
344 
345  // now build the patches in parallel
346  WorkStream::run (&all_faces[0],
347  &all_faces[0]+all_faces.size(),
349  this, std_cxx11::_1, std_cxx11::_2, std_cxx11::_3),
350  std_cxx11::bind(&internal::DataOutFaces::
351  append_patch_to_list<dim,space_dimension>,
352  std_cxx11::_1, std_cxx11::ref(this->patches)),
353  thread_data,
354  sample_patch);
355 }
356 
357 
358 
359 template <int dim, typename DoFHandlerType>
362 {
363  // simply find first active cell with a face on the boundary
364  typename Triangulation<dimension,space_dimension>::active_cell_iterator cell = this->triangulation->begin_active();
365  for (; cell != this->triangulation->end(); ++cell)
366  if (cell->is_locally_owned())
367  for (unsigned int f=0; f<GeometryInfo<dimension>::faces_per_cell; ++f)
368  if (!surface_only || cell->face(f)->at_boundary())
369  return FaceDescriptor(cell, f);
370 
371  // just return an invalid descriptor if we haven't found a locally
372  // owned face. this can happen in parallel where all boundary
373  // faces are owned by other processors
374  return FaceDescriptor();
375 }
376 
377 
378 
379 template <int dim, typename DoFHandlerType>
382 {
383  FaceDescriptor face = old_face;
384 
385  // first check whether the present cell has more faces on the boundary. since
386  // we started with this face, its cell must clearly be locally owned
387  Assert (face.first->is_locally_owned(), ExcInternalError());
388  for (unsigned int f=face.second+1; f<GeometryInfo<dimension>::faces_per_cell; ++f)
389  if (!surface_only || face.first->face(f)->at_boundary())
390  // yup, that is so, so return it
391  {
392  face.second = f;
393  return face;
394  }
395 
396  // otherwise find the next active cell that has a face on the boundary
397 
398  // convert the iterator to an active_iterator and advance this to the next
399  // active cell
400  typename Triangulation<dimension,space_dimension>::active_cell_iterator active_cell = face.first;
401 
402  // increase face pointer by one
403  ++active_cell;
404 
405  // while there are active cells
406  while (active_cell != this->triangulation->end())
407  {
408  // check all the faces of this active cell. but skip it altogether
409  // if it isn't locally owned
410  if (active_cell->is_locally_owned())
411  for (unsigned int f=0; f<GeometryInfo<dimension>::faces_per_cell; ++f)
412  if (!surface_only || active_cell->face(f)->at_boundary())
413  {
414  face.first = active_cell;
415  face.second = f;
416  return face;
417  }
418 
419  // the present cell had no faces on the boundary (or was not locally
420  // owned), so check next cell
421  ++active_cell;
422  }
423 
424  // we fell off the edge, so return with invalid pointer
425  face.first = this->triangulation->end();
426  face.second = 0;
427  return face;
428 }
429 
430 
431 
432 // explicit instantiations
433 #include "data_out_faces.inst"
434 
435 DEAL_II_NAMESPACE_CLOSE
TriaActiveIterator< CellAccessor< dim, spacedim > > active_cell_iterator
Definition: tria.h:1499
Shape function values.
static ::ExceptionBase & ExcInvalidNumberOfSubdivisions(int arg1)
const FiniteElement< dim, spacedim > & get_fe() const
void build_one_patch(const FaceDescriptor *cell_and_face, internal::DataOutFaces::ParallelData< dimension, dimension > &data, DataOutBase::Patch< dimension-1, space_dimension > &patch)
Transformed quadrature points.
Point< spacedim > vertices[GeometryInfo< dim >::vertices_per_cell]
virtual FaceDescriptor first_face()
const std::vector< Point< spacedim > > & get_quadrature_points() const
static ::ExceptionBase & ExcMessage(std::string arg1)
void reinit(const TableIndices< N > &new_size, const bool omit_default_initialization=false)
#define Assert(cond, exc)
Definition: exceptions.h:313
UpdateFlags
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
Abstract base class for mapping classes.
Definition: dof_tools.h:46
virtual FaceDescriptor next_face(const FaceDescriptor &face)
unsigned int n_subdivisions
Second derivatives of shape functions.
const std::vector< Tensor< 1, spacedim > > & get_all_normal_vectors() const
Definition: fe_values.cc:3373
DataOutFaces(const bool surface_only=true)
const unsigned int n_quadrature_points
Definition: fe_values.h:1452
std::pair< cell_iterator, unsigned int > FaceDescriptor
static const unsigned int space_dim
Shape function gradients.
Normal vectors.
void run(const std::vector< std::vector< Iterator > > &colored_iterators, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length=2 *MultithreadInfo::n_threads(), const unsigned int chunk_size=8)
Definition: work_stream.h:1110
static ::ExceptionBase & ExcNotImplemented()
unsigned int size(const unsigned int i) const
virtual void build_patches(const unsigned int n_subdivisions=0)
unsigned int n_components(const DoFHandler< dim, spacedim > &dh)
static ::ExceptionBase & ExcNoTriangulationSelected()
Table< 2, float > data
static ::ExceptionBase & ExcInternalError()
virtual UpdateFlags get_needed_update_flags() const =0