Reference documentation for deal.II version 8.5.1
grid_refinement.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 
17 #include <deal.II/base/template_constraints.h>
18 #include <deal.II/lac/vector.h>
19 #include <deal.II/lac/block_vector_base.h>
20 #include <deal.II/lac/block_vector.h>
21 #include <deal.II/lac/petsc_vector.h>
22 #include <deal.II/lac/petsc_block_vector.h>
23 #include <deal.II/lac/trilinos_vector.h>
24 #include <deal.II/lac/trilinos_block_vector.h>
25 
26 #include <deal.II/grid/grid_refinement.h>
27 #include <deal.II/grid/tria_accessor.h>
28 #include <deal.II/grid/tria_iterator.h>
29 #include <deal.II/grid/tria.h>
30 
31 #include <numeric>
32 #include <algorithm>
33 #include <cmath>
34 #include <functional>
35 #include <fstream>
36 
37 DEAL_II_NAMESPACE_OPEN
38 
39 
40 namespace
41 {
42  namespace internal
43  {
44  template <typename number>
45  inline
46  number
47  max_element (const Vector<number> &criteria)
48  {
49  return *std::max_element(criteria.begin(), criteria.end());
50  }
51 
52 
53  template <typename number>
54  inline
55  number
56  min_element (const Vector<number> &criteria)
57  {
58  return *std::min_element(criteria.begin(), criteria.end());
59  }
60 
61  // Silence a (bogus) warning in clang-3.6 about the following four
62  // functions being unused:
63  DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
64 
65 #ifdef DEAL_II_WITH_PETSC
66  inline
67  PetscScalar
68  max_element (const PETScWrappers::Vector &criteria)
69  {
70  // this is horribly slow (since we have
71  // to get the array of values from PETSc
72  // in every iteration), but works
73  PetscScalar m = 0;
74 #ifndef PETSC_USE_COMPLEX
75  for (unsigned int i=0; i<criteria.size(); ++i)
76  m = std::max (m, criteria(i));
77 #else
78  Assert(false, ExcMessage("The GridRefinement functions should only get real-valued vectors of refinement indicators."
79  " Using these functions with complex-valued PETSc vectors does not make sense."))
80 #endif
81  return m;
82  }
83 
84 
85  inline
86  PetscScalar
87  min_element (const PETScWrappers::Vector &criteria)
88  {
89  // this is horribly slow (since we have
90  // to get the array of values from PETSc
91  // in every iteration), but works
92  PetscScalar m = criteria(0);
93 #ifndef PETSC_USE_COMPLEX
94  for (unsigned int i=1; i<criteria.size(); ++i)
95  m = std::min (m, criteria(i));
96 #else
97  Assert(false, ExcMessage("The GridRefinement functions should only get real-valued vectors of refinement indicators."
98  " Using these functions with complex-valued PETSc vectors does not make sense."))
99 #endif
100  return m;
101  }
102 #endif
103 
104 
105 #ifdef DEAL_II_WITH_TRILINOS
106  inline
107  TrilinosScalar
108  max_element (const TrilinosWrappers::Vector &criteria)
109  {
110  TrilinosScalar m = 0;
111  criteria.trilinos_vector().MaxValue(&m);
112  return m;
113  }
114 
115 
116  inline
117  TrilinosScalar
118  min_element (const TrilinosWrappers::Vector &criteria)
119  {
120  TrilinosScalar m = 0;
121  criteria.trilinos_vector().MinValue(&m);
122  return m;
123  }
124 #endif
125 
126  DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
127 
128  } /* namespace internal */
129 
130 
131  template <typename VectorType>
132  typename constraint_and_return_value<!IsBlockVector<VectorType>::value,
133  typename VectorType::value_type>::type
134  min_element (const VectorType &criteria)
135  {
136  return internal::min_element (criteria);
137  }
138 
139 
140  template <typename VectorType>
141  typename constraint_and_return_value<!IsBlockVector<VectorType>::value,
142  typename VectorType::value_type>::type
143  max_element (const VectorType &criteria)
144  {
145  return internal::max_element (criteria);
146  }
147 
148 
149  template <typename VectorType>
150  typename constraint_and_return_value<IsBlockVector<VectorType>::value,
151  typename VectorType::value_type>::type
152  min_element (const VectorType &criteria)
153  {
154  typename VectorType::value_type t = internal::min_element(criteria.block(0));
155  for (unsigned int b=1; b<criteria.n_blocks(); ++b)
156  t = std::min (t, internal::min_element(criteria.block(b)));
157 
158  return t;
159  }
160 
161 
162  template <typename VectorType>
163  typename constraint_and_return_value<IsBlockVector<VectorType>::value,
164  typename VectorType::value_type>::type
165  max_element (const VectorType &criteria)
166  {
167  typename VectorType::value_type t = internal::max_element(criteria.block(0));
168  for (unsigned int b=1; b<criteria.n_blocks(); ++b)
169  t = std::max (t, internal::max_element(criteria.block(b)));
170 
171  return t;
172  }
173 
174 }
175 
176 
177 namespace
178 {
185  template <class VectorType>
186  void qsort_index (const VectorType &a,
187  std::vector<unsigned int> &ind,
188  int l,
189  int r)
190  {
191  int i,j;
192  typename VectorType::value_type v;
193 
194  if (r<=l)
195  return;
196 
197  v = a(ind[r]);
198  i = l-1;
199  j = r;
200  do
201  {
202  do
203  {
204  ++i;
205  }
206  while ((a(ind[i])>v) && (i<r));
207  do
208  {
209  --j;
210  }
211  while ((a(ind[j])<v) && (j>0));
212 
213  if (i<j)
214  std::swap (ind[i], ind[j]);
215  else
216  std::swap (ind[i], ind[r]);
217  }
218  while (i<j);
219  qsort_index(a,ind,l,i-1);
220  qsort_index(a,ind,i+1,r);
221  }
222 }
223 
224 
225 
226 
227 template <int dim, class VectorType, int spacedim>
229  const VectorType &criteria,
230  const double threshold,
231  const unsigned int max_to_mark)
232 {
233  Assert (criteria.size() == tria.n_active_cells(),
234  ExcDimensionMismatch(criteria.size(), tria.n_active_cells()));
235  Assert (criteria.is_non_negative (), ExcNegativeCriteria());
236 
237  // when all indicators are zero we
238  // do not need to refine but only
239  // to coarsen
240  if (criteria.all_zero())
241  return;
242 
243  const unsigned int n_cells = criteria.size();
244 
245 //TODO: This is undocumented, looks fishy and seems unnecessary
246 
247  double new_threshold=threshold;
248  // when threshold==0 find the
249  // smallest value in criteria
250  // greater 0
251  if (new_threshold==0)
252  {
253  new_threshold = criteria(0);
254  for (unsigned int index=1; index<n_cells; ++index)
255  if (criteria(index)>0
256  && (criteria(index)<new_threshold))
257  new_threshold=criteria(index);
258  }
259 
260  unsigned int marked=0;
262  cell != tria.end(); ++cell)
263  if (std::fabs(criteria(cell->active_cell_index())) >= new_threshold)
264  {
265  if (max_to_mark!=numbers::invalid_unsigned_int && marked>=max_to_mark)
266  break;
267  ++marked;
268  cell->set_refine_flag();
269  }
270 }
271 
272 
273 
274 template <int dim, class VectorType, int spacedim>
276  const VectorType &criteria,
277  const double threshold)
278 {
279  Assert (criteria.size() == tria.n_active_cells(),
280  ExcDimensionMismatch(criteria.size(), tria.n_active_cells()));
281  Assert (criteria.is_non_negative (), ExcNegativeCriteria());
282 
284  cell != tria.end(); ++cell)
285  if (std::fabs(criteria(cell->active_cell_index())) <= threshold)
286  if (!cell->refine_flag_set())
287  cell->set_coarsen_flag();
288 }
289 
290 template <int dim>
291 std::pair<double, double>
293  const unsigned int max_n_cells,
294  const double top_fraction,
295  const double bottom_fraction)
296 {
297  Assert (top_fraction>=0, ExcInvalidParameterValue());
298  Assert (top_fraction<=1, ExcInvalidParameterValue());
299  Assert (bottom_fraction>=0, ExcInvalidParameterValue());
300  Assert (bottom_fraction<=1, ExcInvalidParameterValue());
301  Assert (top_fraction+bottom_fraction <= 1, ExcInvalidParameterValue());
302 
303  double refine_cells = current_n_cells * top_fraction;
304  double coarsen_cells = current_n_cells * bottom_fraction;
305 
306  const double cell_increase_on_refine = GeometryInfo<dim>::max_children_per_cell - 1.0;
307  const double cell_decrease_on_coarsen = 1.0 - 1.0/GeometryInfo<dim>::max_children_per_cell;
308 
309  std::pair<double, double> adjusted_fractions(top_fraction, bottom_fraction);
310  // first we have to see whether we
311  // currently already exceed the target
312  // number of cells
313  if (current_n_cells >= max_n_cells)
314  {
315  // if yes, then we need to stop
316  // refining cells and instead try to
317  // only coarsen as many as it would
318  // take to get to the target
319 
320  // as we have no information on cells
321  // being refined isotropically or
322  // anisotropically, assume isotropic
323  // refinement here, though that may
324  // result in a worse approximation
325  adjusted_fractions.first = 0;
326  coarsen_cells = (current_n_cells - max_n_cells) /
327  cell_decrease_on_coarsen;
328  adjusted_fractions.second = std::min(coarsen_cells/current_n_cells, 1.0);
329  }
330  // otherwise, see if we would exceed the
331  // maximum desired number of cells with the
332  // number of cells that are likely going to
333  // result from refinement. here, each cell
334  // to be refined is replaced by
335  // C=GeometryInfo<dim>::max_children_per_cell
336  // new cells, i.e. there will be C-1 more
337  // cells than before. similarly, C cells
338  // will be replaced by 1
339 
340  // again, this is true for isotropically
341  // refined cells. we take this as an
342  // approximation of a mixed refinement.
343  else if (static_cast<unsigned int>
344  (current_n_cells
345  + refine_cells * cell_increase_on_refine
346  - coarsen_cells * cell_decrease_on_coarsen)
347  >
348  max_n_cells)
349  {
350  // we have to adjust the
351  // fractions. assume we want
352  // alpha*refine_fraction and
353  // alpha*coarsen_fraction as new
354  // fractions and the resulting number
355  // of cells to be equal to
356  // max_n_cells. this leads to the
357  // following equation for alpha
358  const double alpha
359  =
360  1. *
361  (max_n_cells - current_n_cells)
362  /
363  (refine_cells * cell_increase_on_refine
364  - coarsen_cells * cell_decrease_on_coarsen);
365 
366  adjusted_fractions.first = alpha * top_fraction;
367  adjusted_fractions.second = alpha * bottom_fraction;
368  }
369  return (adjusted_fractions);
370 }
371 
372 template <int dim, class VectorType, int spacedim>
373 void
375  const VectorType &criteria,
376  const double top_fraction,
377  const double bottom_fraction,
378  const unsigned int max_n_cells)
379 {
380  // correct number of cells is
381  // checked in @p{refine}
382  Assert ((top_fraction>=0) && (top_fraction<=1), ExcInvalidParameterValue());
383  Assert ((bottom_fraction>=0) && (bottom_fraction<=1), ExcInvalidParameterValue());
384  Assert (top_fraction+bottom_fraction <= 1, ExcInvalidParameterValue());
385  Assert (criteria.is_non_negative (), ExcNegativeCriteria());
386 
387  const std::pair<double, double> adjusted_fractions =
388  adjust_refine_and_coarsen_number_fraction<dim> (criteria.size(),
389  max_n_cells,
390  top_fraction,
391  bottom_fraction);
392 
393  const int refine_cells = static_cast<int>(adjusted_fractions.first * criteria.size());
394  const int coarsen_cells = static_cast<int>(adjusted_fractions.second * criteria.size());
395 
396  if (refine_cells || coarsen_cells)
397  {
399  if (refine_cells)
400  {
401  std::nth_element (tmp.begin(), tmp.begin()+refine_cells,
402  tmp.end(),
403  std::greater<double>());
404  refine (tria, criteria, *(tmp.begin() + refine_cells));
405  }
406 
407  if (coarsen_cells)
408  {
409  std::nth_element (tmp.begin(), tmp.begin()+tmp.size()-coarsen_cells,
410  tmp.end(),
411  std::greater<double>());
412  coarsen (tria, criteria,
413  *(tmp.begin() + tmp.size() - coarsen_cells));
414  }
415  }
416 }
417 
418 
419 
420 template <int dim, typename VectorType, int spacedim>
421 void
423  const VectorType &criteria,
424  const double top_fraction,
425  const double bottom_fraction,
426  const unsigned int max_n_cells)
427 {
428  // correct number of cells is
429  // checked in @p{refine}
430  Assert ((top_fraction>=0) && (top_fraction<=1), ExcInvalidParameterValue());
431  Assert ((bottom_fraction>=0) && (bottom_fraction<=1), ExcInvalidParameterValue());
432  Assert (top_fraction+bottom_fraction <= 1, ExcInvalidParameterValue());
433  Assert (criteria.is_non_negative (), ExcNegativeCriteria());
434 
435  // let tmp be the cellwise square of the
436  // error, which is what we have to sum
437  // up and compare with
438  // @p{fraction_of_error*total_error}.
440  tmp = criteria;
441  const double total_error = tmp.l1_norm();
442 
443  // sort the largest criteria to the
444  // beginning of the vector
445  std::sort (tmp.begin(), tmp.end(), std::greater<double>());
446 
447  // compute thresholds
449  pp=tmp.begin();
450  for (double sum=0;
451  (sum<top_fraction*total_error) && (pp!=(tmp.end()-1));
452  ++pp)
453  sum += *pp;
454  double top_threshold = ( pp != tmp.begin () ?
455  (*pp+*(pp-1))/2 :
456  *pp );
458  qq=(tmp.end()-1);
459  for (double sum=0;
460  (sum<bottom_fraction*total_error) && (qq!=tmp.begin());
461  --qq)
462  sum += *qq;
463  double bottom_threshold = ( qq != (tmp.end()-1) ?
464  (*qq + *(qq+1))/2 :
465  0);
466 
467  // we now have an idea how many cells we
468  // are going to refine and coarsen. we use
469  // this information to see whether we are
470  // over the limit and if so use a function
471  // that knows how to deal with this
472  // situation
473 
474  // note, that at this point, we have no
475  // information about anisotropically refined
476  // cells, thus use the situation of purely
477  // isotropic refinement as guess for a mixed
478  // refinemnt as well.
479  {
480  const unsigned int refine_cells = pp - tmp.begin(),
481  coarsen_cells = tmp.end() - qq;
482 
483  if (static_cast<unsigned int>
484  (tria.n_active_cells()
485  + refine_cells * (GeometryInfo<dim>::max_children_per_cell - 1)
486  - (coarsen_cells *
489  >
490  max_n_cells)
491  {
492  refine_and_coarsen_fixed_number (tria,
493  criteria,
494  1.*refine_cells/criteria.size(),
495  1.*coarsen_cells/criteria.size(),
496  max_n_cells);
497  return;
498  }
499  }
500 
501 
502  // in some rare cases it may happen that
503  // both thresholds are the same (e.g. if
504  // there are many cells with the same
505  // error indicator). That would mean that
506  // all cells will be flagged for
507  // refinement or coarsening, but some will
508  // be flagged for both, namely those for
509  // which the indicator equals the
510  // thresholds. This is forbidden, however.
511  //
512  // In some rare cases with very few cells
513  // we also could get integer round off
514  // errors and get problems with
515  // the top and bottom fractions.
516  //
517  // In these case we arbitrarily reduce the
518  // bottom threshold by one permille below
519  // the top threshold
520  //
521  // Finally, in some cases
522  // (especially involving symmetric
523  // solutions) there are many cells
524  // with the same error indicator
525  // values. if there are many with
526  // indicator equal to the top
527  // threshold, no refinement will
528  // take place below; to avoid this
529  // case, we also lower the top
530  // threshold if it equals the
531  // largest indicator and the
532  // top_fraction!=1
533  if ((top_threshold == max_element(criteria)) &&
534  (top_fraction != 1))
535  top_threshold *= 0.999;
536 
537  if (bottom_threshold>=top_threshold)
538  bottom_threshold = 0.999*top_threshold;
539 
540  // actually flag cells
541  if (top_threshold < max_element(criteria))
542  refine (tria, criteria, top_threshold, pp - tmp.begin());
543 
544  if (bottom_threshold > min_element(criteria))
545  coarsen (tria, criteria, bottom_threshold);
546 }
547 
548 
549 
550 template <int dim, typename VectorType, int spacedim>
551 void
553  const VectorType &criteria,
554  const unsigned int order)
555 {
556  Assert (criteria.size() == tria.n_active_cells(),
557  ExcDimensionMismatch(criteria.size(), tria.n_active_cells()));
558  Assert (criteria.is_non_negative (), ExcNegativeCriteria());
559 
560  // get an increasing order on
561  // the error indicator
562  std::vector<unsigned int> tmp(criteria.size());
563  for (unsigned int i=0; i<criteria.size(); ++i)
564  tmp[i] = i;
565 
566  qsort_index (criteria, tmp, 0, criteria.size()-1);
567 
568  double expected_error_reduction = 0;
569  const double original_error = criteria.l1_norm();
570 
571  const unsigned int N = criteria.size();
572 
573  // minimize the cost functional discussed in the documentation
574  double min_cost = std::numeric_limits<double>::max();
575  unsigned int min_arg = 0;
576 
577  for (unsigned int M = 0; M<criteria.size(); ++M)
578  {
579  expected_error_reduction += (1-std::pow(2.,-1.*order)) * criteria(tmp[M]);
580 
581  const double cost = std::pow(((std::pow(2.,dim)-1)*(1+M)+N),
582  (double)order/dim) *
583  (original_error-expected_error_reduction);
584  if (cost <= min_cost)
585  {
586  min_cost = cost;
587  min_arg = M;
588  }
589  }
590 
591  refine (tria, criteria, criteria(tmp[min_arg]));
592 }
593 
594 
595 // explicit instantiations
596 #include "grid_refinement.inst"
597 
598 DEAL_II_NAMESPACE_CLOSE
unsigned int n_active_cells() const
Definition: tria.cc:11244
void refine_and_coarsen_fixed_number(Triangulation< dim, spacedim > &triangulation, const VectorType &criteria, const double top_fraction_of_cells, const double bottom_fraction_of_cells, const unsigned int max_n_cells=std::numeric_limits< unsigned int >::max())
static const unsigned int invalid_unsigned_int
Definition: types.h:170
real_type l1_norm() const
active_cell_iterator begin_active(const unsigned int level=0) const
Definition: tria.cc:10668
void refine_and_coarsen_fixed_fraction(Triangulation< dim, spacedim > &tria, const VectorType &criteria, const double top_fraction, const double bottom_fraction, const unsigned int max_n_cells=std::numeric_limits< unsigned int >::max())
iterator end()
cell_iterator end() const
Definition: tria.cc:10736
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcNegativeCriteria()
#define Assert(cond, exc)
Definition: exceptions.h:313
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
std::size_t size() const
void coarsen(Triangulation< dim, spacedim > &tria, const VectorType &criteria, const double threshold)
iterator begin()
SymmetricTensor< rank, dim, Number > sum(const SymmetricTensor< rank, dim, Number > &local, const MPI_Comm &mpi_communicator)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
const Epetra_MultiVector & trilinos_vector() const
std::pair< double, double > adjust_refine_and_coarsen_number_fraction(const unsigned int current_n_cells, const unsigned int max_n_cells, const double top_fraction_of_cells, const double bottom_fraction_of_cells)
static ::ExceptionBase & ExcInvalidParameterValue()
void refine(Triangulation< dim, spacedim > &tria, const VectorType &criteria, const double threshold, const unsigned int max_to_mark=numbers::invalid_unsigned_int)
void refine_and_coarsen_optimize(Triangulation< dim, spacedim > &tria, const VectorType &criteria, const unsigned int order=2)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)