Reference documentation for deal.II version 9.0.0
data_out_rotation.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2018 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/grid/tria.h>
21 #include <deal.II/dofs/dof_handler.h>
22 #include <deal.II/dofs/dof_accessor.h>
23 #include <deal.II/grid/tria_iterator.h>
24 #include <deal.II/fe/fe.h>
25 #include <deal.II/fe/fe_values.h>
26 #include <deal.II/hp/fe_values.h>
27 #include <deal.II/fe/mapping_q1.h>
28 #include <deal.II/numerics/data_out_rotation.h>
29 
30 #include <cmath>
31 
32 DEAL_II_NAMESPACE_OPEN
33 
34 
35 //TODO: Update documentation
36 //TODO: Unify code for dimensions
37 
38 
39 //TODO: build_some_patches isn't going to work if first_cell/next_cell
40 //don't iterate over all cells and if cell data is requested. in that
41 //case, we need to calculate cell_number as in the DataOut class
42 
43 // Not implemented for 3D
44 
45 
46 namespace internal
47 {
48  namespace DataOutRotationImplementation
49  {
50  template <int dim, int spacedim>
51  ParallelData<dim,spacedim>::
52  ParallelData (const unsigned int n_datasets,
53  const unsigned int n_subdivisions,
54  const unsigned int n_patches_per_circle,
55  const std::vector<unsigned int> &n_postprocessor_outputs,
56  const Mapping<dim,spacedim> &mapping,
57  const std::vector<std::shared_ptr<::hp::FECollection<dim,spacedim> > > &finite_elements,
58  const UpdateFlags update_flags)
59  :
60  internal::DataOutImplementation::
61  ParallelDataBase<dim,spacedim> (n_datasets,
62  n_subdivisions,
63  n_postprocessor_outputs,
64  mapping,
65  finite_elements,
66  update_flags,
67  false),
68  n_patches_per_circle (n_patches_per_circle)
69  {}
70 
71 
72 
77  template <int dim, int spacedim>
78  void
79  append_patch_to_list (const std::vector<DataOutBase::Patch<dim+1,spacedim+1> > &new_patches,
80  std::vector<DataOutBase::Patch<dim+1,spacedim+1> > &patches)
81  {
82  for (unsigned int i=0; i<new_patches.size(); ++i)
83  {
84  patches.push_back (new_patches[i]);
85  patches.back().patch_index = patches.size()-1;
86  }
87  }
88  }
89 }
90 
91 
92 
93 template <int dim, typename DoFHandlerType>
94 void
98  std::vector<DataOutBase::Patch<dimension+1,space_dimension+1> > &my_patches)
99 {
100  if (dim == 3)
101  {
102  // would this function make any sense after all? who would want to
103  // output/compute in four space dimensions?
104  Assert (false, ExcNotImplemented());
105  return;
106  }
107 
108  Assert ((*cell)->is_locally_owned(),
110 
111  const unsigned int n_patches_per_circle = data.n_patches_per_circle;
112 
113  // another abbreviation denoting the number of q_points in each direction
114  const unsigned int n_points = data.n_subdivisions+1;
115 
116  // set up an array that holds the directions in the plane of rotation in
117  // which we will put points in the whole domain (not the rotationally
118  // reduced one in which the computation took place. for simplicity add the
119  // initial direction at the end again
120  std::vector<Point<dimension+1> > angle_directions (n_patches_per_circle+1);
121  for (unsigned int i=0; i<=n_patches_per_circle; ++i)
122  {
123  angle_directions[i][dimension-1] = std::cos(2*numbers::PI *
124  i/n_patches_per_circle);
125  angle_directions[i][dimension] = std::sin(2*numbers::PI *
126  i/n_patches_per_circle);
127  }
128 
129  for (unsigned int angle=0; angle<n_patches_per_circle; ++angle)
130  {
131  // first compute the vertices of the patch. note that they will have to
132  // be computed from the vertices of the cell, which has one dimension
133  // less, however.
134  switch (dimension)
135  {
136  case 1:
137  {
138  const double r1 = (*cell)->vertex(0)(0),
139  r2 = (*cell)->vertex(1)(0);
140  Assert (r1 >= 0, ExcRadialVariableHasNegativeValues(r1));
141  Assert (r2 >= 0, ExcRadialVariableHasNegativeValues(r2));
142 
143  my_patches[angle].vertices[0] = r1*angle_directions[angle];
144  my_patches[angle].vertices[1] = r2*angle_directions[angle];
145  my_patches[angle].vertices[2] = r1*angle_directions[angle+1];
146  my_patches[angle].vertices[3] = r2*angle_directions[angle+1];
147 
148  break;
149  };
150 
151  case 2:
152  {
153  for (unsigned int vertex=0;
154  vertex<GeometryInfo<dimension>::vertices_per_cell;
155  ++vertex)
156  {
157  const Point<dimension> v = (*cell)->vertex(vertex);
158 
159  // make sure that the radial variable is nonnegative
160  Assert (v(0) >= 0, ExcRadialVariableHasNegativeValues(v(0)));
161 
162  // now set the vertices of the patch
163  my_patches[angle].vertices[vertex] = v(0) * angle_directions[angle];
164  my_patches[angle].vertices[vertex][0] = v(1);
165 
166  my_patches[angle].vertices[vertex+GeometryInfo<dimension>::vertices_per_cell]
167  = v(0) * angle_directions[angle+1];
168  my_patches[angle].vertices[vertex+GeometryInfo<dimension>::vertices_per_cell][0]
169  = v(1);
170  };
171 
172  break;
173  };
174 
175  default:
176  Assert (false, ExcNotImplemented());
177  };
178 
179  // then fill in data
180  if (data.n_datasets > 0)
181  {
182  unsigned int offset=0;
183 
184  data.reinit_all_fe_values(this->dof_data, *cell);
185  // first fill dof_data
186  for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
187  {
188  const FEValuesBase<dimension> &fe_patch_values
189  = data.get_present_fe_values(dataset);
190  const unsigned int n_components
191  = fe_patch_values.get_fe().n_components();
192  const DataPostprocessor<dim> *postprocessor=this->dof_data[dataset]->postprocessor;
193  if (postprocessor != nullptr)
194  {
195  // we have to postprocess the
196  // data, so determine, which
197  // fields have to be updated
198  const UpdateFlags update_flags=postprocessor->get_needed_update_flags();
199 
200  if (n_components == 1)
201  {
202  // at each point there is
203  // only one component of
204  // value, gradient etc.
205  if (update_flags & update_values)
206  this->dof_data[dataset]->get_function_values (fe_patch_values,
207  internal::DataOutImplementation::ComponentExtractor::real_part,
208  data.patch_values_scalar.solution_values);
209  if (update_flags & update_gradients)
210  this->dof_data[dataset]->get_function_gradients (fe_patch_values,
211  internal::DataOutImplementation::ComponentExtractor::real_part,
212  data.patch_values_scalar.solution_gradients);
213  if (update_flags & update_hessians)
214  this->dof_data[dataset]->get_function_hessians (fe_patch_values,
215  internal::DataOutImplementation::ComponentExtractor::real_part,
216  data.patch_values_scalar.solution_hessians);
217 
218  if (update_flags & update_quadrature_points)
219  data.patch_values_scalar.evaluation_points = fe_patch_values.get_quadrature_points();
220 
221  const typename DoFHandlerType::active_cell_iterator dh_cell(&(*cell)->get_triangulation(),
222  (*cell)->level(),
223  (*cell)->index(),
224  this->dof_data[dataset]->dof_handler);
225  data.patch_values_scalar.template set_cell<DoFHandlerType> (dh_cell);
226 
227  postprocessor->
228  evaluate_scalar_field(data.patch_values_scalar,
229  data.postprocessed_values[dataset]);
230  }
231  else
232  {
233  data.resize_system_vectors(n_components);
234 
235  // at each point there is a vector valued function and
236  // its derivative...
237  if (update_flags & update_values)
238  this->dof_data[dataset]->get_function_values (fe_patch_values,
239  internal::DataOutImplementation::ComponentExtractor::real_part,
240  data.patch_values_system.solution_values);
241  if (update_flags & update_gradients)
242  this->dof_data[dataset]->get_function_gradients (fe_patch_values,
243  internal::DataOutImplementation::ComponentExtractor::real_part,
244  data.patch_values_system.solution_gradients);
245  if (update_flags & update_hessians)
246  this->dof_data[dataset]->get_function_hessians (fe_patch_values,
247  internal::DataOutImplementation::ComponentExtractor::real_part,
248  data.patch_values_system.solution_hessians);
249 
250  if (update_flags & update_quadrature_points)
251  data.patch_values_system.evaluation_points = fe_patch_values.get_quadrature_points();
252 
253  const typename DoFHandlerType::active_cell_iterator dh_cell(&(*cell)->get_triangulation(),
254  (*cell)->level(),
255  (*cell)->index(),
256  this->dof_data[dataset]->dof_handler);
257  data.patch_values_system.template set_cell<DoFHandlerType> (dh_cell);
258 
259  postprocessor->
260  evaluate_vector_field(data.patch_values_system,
261  data.postprocessed_values[dataset]);
262  }
263 
264  for (unsigned int component=0;
265  component<this->dof_data[dataset]->n_output_variables;
266  ++component)
267  {
268  switch (dimension)
269  {
270  case 1:
271  for (unsigned int x=0; x<n_points; ++x)
272  for (unsigned int y=0; y<n_points; ++y)
273  my_patches[angle].data(offset+component,
274  x*n_points + y)
275  = data.postprocessed_values[dataset][x](component);
276  break;
277 
278  case 2:
279  for (unsigned int x=0; x<n_points; ++x)
280  for (unsigned int y=0; y<n_points; ++y)
281  for (unsigned int z=0; z<n_points; ++z)
282  my_patches[angle].data(offset+component,
283  x*n_points*n_points +
284  y*n_points +
285  z)
286  = data.postprocessed_values[dataset][x*n_points+z](component);
287  break;
288 
289  default:
290  Assert (false, ExcNotImplemented());
291  }
292  }
293  }
294  else if (n_components == 1)
295  {
296  this->dof_data[dataset]->get_function_values (fe_patch_values,
297  internal::DataOutImplementation::ComponentExtractor::real_part,
298  data.patch_values_scalar.solution_values);
299 
300  switch (dimension)
301  {
302  case 1:
303  for (unsigned int x=0; x<n_points; ++x)
304  for (unsigned int y=0; y<n_points; ++y)
305  my_patches[angle].data(offset,
306  x*n_points + y)
307  = data.patch_values_scalar.solution_values[x];
308  break;
309 
310  case 2:
311  for (unsigned int x=0; x<n_points; ++x)
312  for (unsigned int y=0; y<n_points; ++y)
313  for (unsigned int z=0; z<n_points; ++z)
314  my_patches[angle].data(offset,
315  x*n_points*n_points +
316  y +
317  z*n_points)
318  = data.patch_values_scalar.solution_values[x*n_points+z];
319  break;
320 
321  default:
322  Assert (false, ExcNotImplemented());
323  }
324  }
325  else
326  // system of components
327  {
328  data.resize_system_vectors(n_components);
329  this->dof_data[dataset]->get_function_values (fe_patch_values,
330  internal::DataOutImplementation::ComponentExtractor::real_part,
331  data.patch_values_system.solution_values);
332 
333  for (unsigned int component=0; component<n_components;
334  ++component)
335  {
336  switch (dimension)
337  {
338  case 1:
339  for (unsigned int x=0; x<n_points; ++x)
340  for (unsigned int y=0; y<n_points; ++y)
341  my_patches[angle].data(offset+component,
342  x*n_points + y)
343  = data.patch_values_system.solution_values[x](component);
344  break;
345 
346  case 2:
347  for (unsigned int x=0; x<n_points; ++x)
348  for (unsigned int y=0; y<n_points; ++y)
349  for (unsigned int z=0; z<n_points; ++z)
350  my_patches[angle].data(offset+component,
351  x*n_points*n_points +
352  y*n_points +
353  z)
354  = data.patch_values_system.solution_values[x*n_points+z](component);
355  break;
356 
357  default:
358  Assert (false, ExcNotImplemented());
359  }
360  }
361  }
362  offset+=this->dof_data[dataset]->n_output_variables;
363  }
364 
365  // then do the cell data
366  for (unsigned int dataset=0; dataset<this->cell_data.size(); ++dataset)
367  {
368  // we need to get at the number of the cell to which this face
369  // belongs in order to access the cell data. this is not readily
370  // available, so choose the following rather inefficient way:
371  Assert ((*cell)->active(),
372  ExcMessage("Cell must be active for cell data"));
373  const unsigned int cell_number
374  = std::distance (this->triangulation->begin_active(),
376  const double value
377  = this->cell_data[dataset]->get_cell_data_value (cell_number,
378  internal::DataOutImplementation::ComponentExtractor::real_part);
379  switch (dimension)
380  {
381  case 1:
382  for (unsigned int x=0; x<n_points; ++x)
383  for (unsigned int y=0; y<n_points; ++y)
384  my_patches[angle].data(dataset+offset,
385  x*n_points +
386  y)
387  = value;
388  break;
389 
390  case 2:
391  for (unsigned int x=0; x<n_points; ++x)
392  for (unsigned int y=0; y<n_points; ++y)
393  for (unsigned int z=0; z<n_points; ++z)
394  my_patches[angle].data(dataset+offset,
395  x*n_points*n_points +
396  y*n_points +
397  z)
398  = value;
399  break;
400 
401  default:
402  Assert (false, ExcNotImplemented());
403  }
404  }
405  }
406  }
407 }
408 
409 
410 
411 template <int dim, typename DoFHandlerType>
412 void DataOutRotation<dim,DoFHandlerType>::build_patches (const unsigned int n_patches_per_circle,
413  const unsigned int nnnn_subdivisions)
414 {
415  // Check consistency of redundant
416  // template parameter
417  Assert (dim==dimension, ExcDimensionMismatch(dim, dimension));
418  Assert (this->triangulation != nullptr,
420 
421  const unsigned int n_subdivisions = (nnnn_subdivisions != 0)
422  ? nnnn_subdivisions
423  : this->default_subdivisions;
424  Assert (n_subdivisions >= 1,
426 
427  this->validate_dataset_names();
428 
429  unsigned int n_datasets=this->cell_data.size();
430  for (unsigned int i=0; i<this->dof_data.size(); ++i)
431  n_datasets+= this->dof_data[i]->n_output_variables;
432 
434  for (unsigned int i=0; i<this->dof_data.size(); ++i)
435  if (this->dof_data[i]->postprocessor)
436  update_flags |= this->dof_data[i]->postprocessor->get_needed_update_flags();
437  // perhaps update_normal_vectors is present,
438  // which would only be useful on faces, but
439  // we may not use it here.
440  Assert (!(update_flags & update_normal_vectors),
441  ExcMessage("The update of normal vectors may not be requested for "
442  "evaluation of data on cells via DataPostprocessor."));
443 
444  // first count the cells we want to
445  // create patches of and make sure
446  // there is enough memory for that
447  std::vector<cell_iterator> all_cells;
448  for (cell_iterator cell=first_cell(); cell != this->triangulation->end();
449  cell = next_cell(cell))
450  all_cells.push_back (cell);
451 
452  // then also take into account that
453  // we want more than one patch to
454  // come out of every cell, as they
455  // are repeated around the axis of
456  // rotation
457  this->patches.clear();
458  this->patches.reserve (all_cells.size() * n_patches_per_circle);
459 
460 
461  std::vector<unsigned int> n_postprocessor_outputs (this->dof_data.size());
462  for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
463  if (this->dof_data[dataset]->postprocessor)
464  n_postprocessor_outputs[dataset] = this->dof_data[dataset]->n_output_variables;
465  else
466  n_postprocessor_outputs[dataset] = 0;
467 
469  thread_data (n_datasets,
470  n_subdivisions, n_patches_per_circle,
471  n_postprocessor_outputs,
473  this->get_fes(),
474  update_flags);
475  std::vector<DataOutBase::Patch<dimension+1,space_dimension+1> >
476  new_patches (n_patches_per_circle);
477  for (unsigned int i=0; i<new_patches.size(); ++i)
478  {
479  new_patches[i].n_subdivisions = n_subdivisions;
480  new_patches[i].data.reinit (n_datasets,
481  Utilities::fixed_power<dimension+1>(n_subdivisions+1));
482  }
483 
484  // now build the patches in parallel
485  WorkStream::run (&all_cells[0],
486  &all_cells[0]+all_cells.size(),
488  this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
490  ::append_patch_to_list<dim,space_dimension>,
491  std::placeholders::_1, std::ref(this->patches)),
492  thread_data,
493  new_patches);
494 }
495 
496 
497 
498 template <int dim, typename DoFHandlerType>
501 {
502  return this->triangulation->begin_active ();
503 }
504 
505 
506 template <int dim, typename DoFHandlerType>
509 {
510  // convert the iterator to an
511  // active_iterator and advance
512  // this to the next active cell
514  ++active_cell;
515  return active_cell;
516 }
517 
518 
519 
520 // explicit instantiations
521 #include "data_out_rotation.inst"
522 
523 
524 DEAL_II_NAMESPACE_CLOSE
TriaActiveIterator< CellAccessor< dim, spacedim > > active_cell_iterator
Definition: tria.h:1527
Shape function values.
static ::ExceptionBase & ExcNoTriangulationSelected()
virtual cell_iterator next_cell(const cell_iterator &cell)
const FiniteElement< dim, spacedim > & get_fe() const
Transformed quadrature points.
static ::ExceptionBase & ExcInvalidNumberOfSubdivisions(int arg1)
Definition: point.h:104
const std::vector< Point< spacedim > > & get_quadrature_points() const
static const double PI
Definition: numbers.h:127
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1142
UpdateFlags
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
Abstract base class for mapping classes.
Definition: dof_tools.h:46
Second derivatives of shape functions.
virtual cell_iterator first_cell()
virtual void build_patches(const unsigned int n_patches_per_circle, const unsigned int n_subdivisions=0)
DataOut_DoFData< DoFHandlerType, dimension+1 >::cell_iterator cell_iterator
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:1106
static ::ExceptionBase & ExcNotImplemented()
unsigned int n_components(const DoFHandler< dim, spacedim > &dh)
void build_one_patch(const cell_iterator *cell, internal::DataOutRotationImplementation::ParallelData< dimension, space_dimension > &data, std::vector< DataOutBase::Patch< dimension+1, space_dimension+1 > > &my_patches)
virtual UpdateFlags get_needed_update_flags() const =0