Reference documentation for deal.II version 8.4.2
data_out_rotation.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 #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 DataOutRotation
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_cxx11::shared_ptr<::hp::FECollection<dim,spacedim> > > &finite_elements,
58  const UpdateFlags update_flags)
59  :
60  internal::DataOut::
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,
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
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(),
109  ExcNotImplemented());
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  patches[angle].vertices[0] = r1*angle_directions[angle];
144  patches[angle].vertices[1] = r2*angle_directions[angle];
145  patches[angle].vertices[2] = r1*angle_directions[angle+1];
146  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 does attain negative
160  // values
161  Assert (v(0) >= 0, ExcRadialVariableHasNegativeValues(v(0)));
162 
163  // now set the vertices of the patch
164  patches[angle].vertices[vertex] = v(0) * angle_directions[angle];
165  patches[angle].vertices[vertex][0] = v(1);
166 
168  = v(0) * angle_directions[angle+1];
169  patches[angle].vertices[vertex+GeometryInfo<dimension>::vertices_per_cell][0]
170  = v(1);
171  };
172 
173  break;
174  };
175 
176  default:
177  Assert (false, ExcNotImplemented());
178  };
179 
180  unsigned int offset=0;
181 
182  // then fill in data
183  if (data.n_datasets > 0)
184  {
185  data.reinit_all_fe_values(this->dof_data, *cell);
186  // first fill dof_data
187  for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
188  {
189  const FEValuesBase<dimension> &fe_patch_values
190  = data.get_present_fe_values(dataset);
191  const unsigned int n_components
192  = fe_patch_values.get_fe().n_components();
193  const DataPostprocessor<dim> *postprocessor=this->dof_data[dataset]->postprocessor;
194  if (postprocessor != 0)
195  {
196  // we have to postprocess the
197  // data, so determine, which
198  // fields have to be updated
199  const UpdateFlags update_flags=postprocessor->get_needed_update_flags();
200 
201  if (n_components == 1)
202  {
203  // at each point there is
204  // only one component of
205  // value, gradient etc.
206  if (update_flags & update_values)
207  this->dof_data[dataset]->get_function_values (fe_patch_values,
208  data.patch_values);
209  if (update_flags & update_gradients)
210  this->dof_data[dataset]->get_function_gradients (fe_patch_values,
211  data.patch_gradients);
212  if (update_flags & update_hessians)
213  this->dof_data[dataset]->get_function_hessians (fe_patch_values,
214  data.patch_hessians);
215 
216  if (update_flags & update_quadrature_points)
217  data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
218 
219  std::vector<Point<space_dimension> > dummy_normals;
220  postprocessor->
221  compute_derived_quantities_scalar(data.patch_values,
222  data.patch_gradients,
223  data.patch_hessians,
224  dummy_normals,
225  data.patch_evaluation_points,
226  data.postprocessed_values[dataset]);
227  }
228  else
229  {
230  data.resize_system_vectors(n_components);
231 
232  // at each point there is a vector valued function and
233  // its derivative...
234  if (update_flags & update_values)
235  this->dof_data[dataset]->get_function_values (fe_patch_values,
236  data.patch_values_system);
237  if (update_flags & update_gradients)
238  this->dof_data[dataset]->get_function_gradients (fe_patch_values,
239  data.patch_gradients_system);
240  if (update_flags & update_hessians)
241  this->dof_data[dataset]->get_function_hessians (fe_patch_values,
242  data.patch_hessians_system);
243 
244  if (update_flags & update_quadrature_points)
245  data.patch_evaluation_points = fe_patch_values.get_quadrature_points();
246 
247  std::vector<Point<space_dimension> > dummy_normals;
248  postprocessor->
249  compute_derived_quantities_vector(data.patch_values_system,
250  data.patch_gradients_system,
251  data.patch_hessians_system,
252  dummy_normals,
253  data.patch_evaluation_points,
254  data.postprocessed_values[dataset]);
255  }
256 
257  for (unsigned int component=0;
258  component<this->dof_data[dataset]->n_output_variables;
259  ++component)
260  {
261  switch (dimension)
262  {
263  case 1:
264  for (unsigned int x=0; x<n_points; ++x)
265  for (unsigned int y=0; y<n_points; ++y)
266  patches[angle].data(offset+component,
267  x*n_points + y)
268  = data.postprocessed_values[dataset][x](component);
269  break;
270 
271  case 2:
272  for (unsigned int x=0; x<n_points; ++x)
273  for (unsigned int y=0; y<n_points; ++y)
274  for (unsigned int z=0; z<n_points; ++z)
275  patches[angle].data(offset+component,
276  x*n_points*n_points +
277  y*n_points +
278  z)
279  = data.postprocessed_values[dataset][x*n_points+z](component);
280  break;
281 
282  default:
283  Assert (false, ExcNotImplemented());
284  }
285  }
286  }
287  else if (n_components == 1)
288  {
289  this->dof_data[dataset]->get_function_values (fe_patch_values,
290  data.patch_values);
291 
292  switch (dimension)
293  {
294  case 1:
295  for (unsigned int x=0; x<n_points; ++x)
296  for (unsigned int y=0; y<n_points; ++y)
297  patches[angle].data(offset,
298  x*n_points + y)
299  = data.patch_values[x];
300  break;
301 
302  case 2:
303  for (unsigned int x=0; x<n_points; ++x)
304  for (unsigned int y=0; y<n_points; ++y)
305  for (unsigned int z=0; z<n_points; ++z)
306  patches[angle].data(offset,
307  x*n_points*n_points +
308  y +
309  z*n_points)
310  = data.patch_values[x*n_points+z];
311  break;
312 
313  default:
314  Assert (false, ExcNotImplemented());
315  }
316  }
317  else
318  // system of components
319  {
320  data.resize_system_vectors(n_components);
321  this->dof_data[dataset]->get_function_values (fe_patch_values,
322  data.patch_values_system);
323 
324  for (unsigned int component=0; component<n_components;
325  ++component)
326  {
327  switch (dimension)
328  {
329  case 1:
330  for (unsigned int x=0; x<n_points; ++x)
331  for (unsigned int y=0; y<n_points; ++y)
332  patches[angle].data(offset+component,
333  x*n_points + y)
334  = data.patch_values_system[x](component);
335  break;
336 
337  case 2:
338  for (unsigned int x=0; x<n_points; ++x)
339  for (unsigned int y=0; y<n_points; ++y)
340  for (unsigned int z=0; z<n_points; ++z)
341  patches[angle].data(offset+component,
342  x*n_points*n_points +
343  y*n_points +
344  z)
345  = data.patch_values_system[x*n_points+z](component);
346  break;
347 
348  default:
349  Assert (false, ExcNotImplemented());
350  }
351  }
352  }
353  offset+=this->dof_data[dataset]->n_output_variables;
354  }
355 
356  // then do the cell data
357  for (unsigned int dataset=0; dataset<this->cell_data.size(); ++dataset)
358  {
359  // we need to get at the number of the cell to which this face
360  // belongs in order to access the cell data. this is not readily
361  // available, so choose the following rather inefficient way:
362  Assert ((*cell)->active(),
363  ExcMessage("Cell must be active for cell data"));
364  const unsigned int cell_number
365  = std::distance (this->triangulation->begin_active(),
367  const double value
368  = this->cell_data[dataset]->get_cell_data_value (cell_number);
369  switch (dimension)
370  {
371  case 1:
372  for (unsigned int x=0; x<n_points; ++x)
373  for (unsigned int y=0; y<n_points; ++y)
374  patches[angle].data(dataset+offset,
375  x*n_points +
376  y)
377  = value;
378  break;
379 
380  case 2:
381  for (unsigned int x=0; x<n_points; ++x)
382  for (unsigned int y=0; y<n_points; ++y)
383  for (unsigned int z=0; z<n_points; ++z)
384  patches[angle].data(dataset+offset,
385  x*n_points*n_points +
386  y*n_points +
387  z)
388  = value;
389  break;
390 
391  default:
392  Assert (false, ExcNotImplemented());
393  }
394  }
395  }
396  }
397 }
398 
399 
400 
401 template <int dim, typename DoFHandlerType>
402 void DataOutRotation<dim,DoFHandlerType>::build_patches (const unsigned int n_patches_per_circle,
403  const unsigned int nnnn_subdivisions)
404 {
405  // Check consistency of redundant
406  // template parameter
407  Assert (dim==dimension, ExcDimensionMismatch(dim, dimension));
408  Assert (this->triangulation != 0,
409  Exceptions::DataOut::ExcNoTriangulationSelected());
410 
411  const unsigned int n_subdivisions = (nnnn_subdivisions != 0)
412  ? nnnn_subdivisions
413  : this->default_subdivisions;
414  Assert (n_subdivisions >= 1,
415  Exceptions::DataOut::ExcInvalidNumberOfSubdivisions(n_subdivisions));
416 
417  unsigned int n_datasets=this->cell_data.size();
418  for (unsigned int i=0; i<this->dof_data.size(); ++i)
419  n_datasets+= this->dof_data[i]->n_output_variables;
420 
422  for (unsigned int i=0; i<this->dof_data.size(); ++i)
423  if (this->dof_data[i]->postprocessor)
424  update_flags |= this->dof_data[i]->postprocessor->get_needed_update_flags();
425  // perhaps update_normal_vectors is present,
426  // which would only be useful on faces, but
427  // we may not use it here.
428  Assert (!(update_flags & update_normal_vectors),
429  ExcMessage("The update of normal vectors may not be requested for "
430  "evaluation of data on cells via DataPostprocessor."));
431 
432  // first count the cells we want to
433  // create patches of and make sure
434  // there is enough memory for that
435  std::vector<cell_iterator> all_cells;
436  for (cell_iterator cell=first_cell(); cell != this->triangulation->end();
437  cell = next_cell(cell))
438  all_cells.push_back (cell);
439 
440  // then also take into account that
441  // we want more than one patch to
442  // come out of every cell, as they
443  // are repeated around the axis of
444  // rotation
445  this->patches.clear();
446  this->patches.reserve (all_cells.size() * n_patches_per_circle);
447 
448 
449  std::vector<unsigned int> n_postprocessor_outputs (this->dof_data.size());
450  for (unsigned int dataset=0; dataset<this->dof_data.size(); ++dataset)
451  if (this->dof_data[dataset]->postprocessor)
452  n_postprocessor_outputs[dataset] = this->dof_data[dataset]->n_output_variables;
453  else
454  n_postprocessor_outputs[dataset] = 0;
455 
457  thread_data (n_datasets,
458  n_subdivisions, n_patches_per_circle,
459  n_postprocessor_outputs,
461  this->get_finite_elements(),
462  update_flags);
463  std::vector<DataOutBase::Patch<dimension+1,space_dimension+1> >
464  new_patches (n_patches_per_circle);
465  for (unsigned int i=0; i<new_patches.size(); ++i)
466  {
467  new_patches[i].n_subdivisions = n_subdivisions;
468  new_patches[i].data.reinit (n_datasets,
469  Utilities::fixed_power<dimension+1>(n_subdivisions+1));
470  }
471 
472  // now build the patches in parallel
473  WorkStream::run (&all_cells[0],
474  &all_cells[0]+all_cells.size(),
476  this, std_cxx11::_1, std_cxx11::_2, std_cxx11::_3),
477  std_cxx11::bind(&internal::DataOutRotation
478  ::append_patch_to_list<dim,space_dimension>,
479  std_cxx11::_1, std_cxx11::ref(this->patches)),
480  thread_data,
481  new_patches);
482 }
483 
484 
485 
486 template <int dim, typename DoFHandlerType>
489 {
490  return this->triangulation->begin_active ();
491 }
492 
493 
494 template <int dim, typename DoFHandlerType>
497 {
498  // convert the iterator to an
499  // active_iterator and advance
500  // this to the next active cell
502  ++active_cell;
503  return active_cell;
504 }
505 
506 
507 
508 // explicit instantiations
509 #include "data_out_rotation.inst"
510 
511 
512 DEAL_II_NAMESPACE_CLOSE
std::vector< std_cxx11::shared_ptr< internal::DataOut::DataEntryBase< DoFHandlerType > > > cell_data
TriaActiveIterator< CellAccessor< dim, spacedim > > active_cell_iterator
Definition: tria.h:1410
Shape function values.
virtual cell_iterator next_cell(const cell_iterator &cell)
::ExceptionBase & ExcMessage(std::string arg1)
void build_one_patch(const cell_iterator *cell, internal::DataOutRotation::ParallelData< dimension, space_dimension > &data, std::vector< DataOutBase::Patch< dimension+1, space_dimension+1 > > &patches)
const FiniteElement< dim, spacedim > & get_fe() const
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: tria.cc:10397
Transformed quadrature points.
static const unsigned int dimension
Definition: point.h:89
cell_iterator end() const
Definition: tria.cc:10465
const std::vector< Point< spacedim > > & get_quadrature_points() const
static const double PI
Definition: numbers.h:74
#define Assert(cond, exc)
Definition: exceptions.h:294
UpdateFlags
Abstract base class for mapping classes.
Definition: dof_tools.h:52
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
std::vector< std_cxx11::shared_ptr<::hp::FECollection< DoFHandlerType::dimension, DoFHandlerType::space_dimension > > > get_finite_elements() const
Shape function gradients.
Normal vectors.
SmartPointer< const Triangulation< DoFHandlerType::dimension, DoFHandlerType::space_dimension > > triangulation
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:1119
std::vector< std_cxx11::shared_ptr< internal::DataOut::DataEntryBase< DoFHandlerType > > > dof_data
virtual UpdateFlags get_needed_update_flags() const =0