mesh_refinement_flagging.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // Local includes
21 #include "libmesh/libmesh_config.h"
22 
23 // only compile these functions if the user requests AMR support
24 #ifdef LIBMESH_ENABLE_AMR
25 
26 // C++ includes
27 #include <algorithm> // for std::sort
28 
29 // Local includes
30 #include "libmesh/elem.h"
31 #include "libmesh/error_vector.h"
33 #include "libmesh/mesh_base.h"
34 #include "libmesh/parallel.h"
35 #include "libmesh/remote_elem.h"
36 
37 namespace libMesh
38 {
39 
40 
41 
42 //-----------------------------------------------------------------
43 // Mesh refinement methods
45  const Real refine_frac,
46  const Real coarsen_frac,
47  const unsigned int max_l)
48 {
49  parallel_object_only();
50 
51  // The function arguments are currently just there for
52  // backwards_compatibility
54  {
55  // If the user used non-default parameters, lets warn
56  // that they're deprecated
57  if (refine_frac != 0.3 ||
58  coarsen_frac != 0.0 ||
59  max_l != libMesh::invalid_uint)
60  libmesh_deprecated();
61 
62  _refine_fraction = refine_frac;
63  _coarsen_fraction = coarsen_frac;
64  _max_h_level = max_l;
65  }
66 
67  // Check for valid fractions..
68  // The fraction values must be in [0,1]
69  libmesh_assert_greater_equal (_refine_fraction, 0);
70  libmesh_assert_less_equal (_refine_fraction, 1);
71  libmesh_assert_greater_equal (_coarsen_fraction, 0);
72  libmesh_assert_less_equal (_coarsen_fraction, 1);
73 
74  // Clean up the refinement flags. These could be left
75  // over from previous refinement steps.
76  this->clean_refinement_flags();
77 
78  // We're getting the minimum and maximum error values
79  // for the ACTIVE elements
80  Real error_min = 1.e30;
81  Real error_max = 0.;
82 
83  // And, if necessary, for their parents
84  Real parent_error_min = 1.e30;
85  Real parent_error_max = 0.;
86 
87  // Prepare another error vector if we need to sum parent errors
88  ErrorVector error_per_parent;
90  {
91  create_parent_error_vector(error_per_cell,
92  error_per_parent,
93  parent_error_min,
94  parent_error_max);
95  }
96 
97  // We need to loop over all active elements to find the minimum
98  for (auto & elem : _mesh.active_local_element_ptr_range())
99  {
100  const dof_id_type id = elem->id();
101  libmesh_assert_less (id, error_per_cell.size());
102 
103  error_max = std::max (error_max, error_per_cell[id]);
104  error_min = std::min (error_min, error_per_cell[id]);
105  }
106  this->comm().max(error_max);
107  this->comm().min(error_min);
108 
109  // Compute the cutoff values for coarsening and refinement
110  const Real error_delta = (error_max - error_min);
111  const Real parent_error_delta = parent_error_max - parent_error_min;
112 
113  const Real refine_cutoff = (1.- _refine_fraction)*error_max;
114  const Real coarsen_cutoff = _coarsen_fraction*error_delta + error_min;
115  const Real parent_cutoff = _coarsen_fraction*parent_error_delta + error_min;
116 
117  // // Print information about the error
118  // libMesh::out << " Error Information:" << std::endl
119  // << " ------------------" << std::endl
120  // << " min: " << error_min << std::endl
121  // << " max: " << error_max << std::endl
122  // << " delta: " << error_delta << std::endl
123  // << " refine_cutoff: " << refine_cutoff << std::endl
124  // << " coarsen_cutoff: " << coarsen_cutoff << std::endl;
125 
126 
127 
128  // Loop over the elements and flag them for coarsening or
129  // refinement based on the element error
130  for (auto & elem : _mesh.active_element_ptr_range())
131  {
132  const dof_id_type id = elem->id();
133 
134  libmesh_assert_less (id, error_per_cell.size());
135 
136  const ErrorVectorReal elem_error = error_per_cell[id];
137 
139  {
140  Elem * parent = elem->parent();
141  if (parent)
142  {
143  const dof_id_type parentid = parent->id();
144  if (error_per_parent[parentid] >= 0. &&
145  error_per_parent[parentid] <= parent_cutoff)
146  elem->set_refinement_flag(Elem::COARSEN);
147  }
148  }
149  // Flag the element for coarsening if its error
150  // is <= coarsen_fraction*delta + error_min
151  else if (elem_error <= coarsen_cutoff)
152  {
153  elem->set_refinement_flag(Elem::COARSEN);
154  }
155 
156  // Flag the element for refinement if its error
157  // is >= refinement_cutoff.
158  if (elem_error >= refine_cutoff)
159  if (elem->level() < _max_h_level)
160  elem->set_refinement_flag(Elem::REFINE);
161  }
162 }
163 
164 
165 
167 {
168  parallel_object_only();
169 
170  libmesh_assert_greater (_coarsen_threshold, 0);
171 
172  // Check for valid fractions..
173  // The fraction values must be in [0,1]
174  libmesh_assert_greater_equal (_refine_fraction, 0);
175  libmesh_assert_less_equal (_refine_fraction, 1);
176  libmesh_assert_greater_equal (_coarsen_fraction, 0);
177  libmesh_assert_less_equal (_coarsen_fraction, 1);
178 
179  // How much error per cell will we tolerate?
180  const Real local_refinement_tolerance =
181  _absolute_global_tolerance / std::sqrt(static_cast<Real>(_mesh.n_active_elem()));
182  const Real local_coarsening_tolerance =
183  local_refinement_tolerance * _coarsen_threshold;
184 
185  // Prepare another error vector if we need to sum parent errors
186  ErrorVector error_per_parent;
188  {
189  Real parent_error_min, parent_error_max;
190 
191  create_parent_error_vector(error_per_cell_in,
192  error_per_parent,
193  parent_error_min,
194  parent_error_max);
195  }
196 
197  for (auto & elem : _mesh.active_element_ptr_range())
198  {
199  Elem * parent = elem->parent();
200  const dof_id_type elem_number = elem->id();
201  const ErrorVectorReal elem_error = error_per_cell_in[elem_number];
202 
203  if (elem_error > local_refinement_tolerance &&
204  elem->level() < _max_h_level)
205  elem->set_refinement_flag(Elem::REFINE);
206 
207  if (!_coarsen_by_parents && elem_error <
208  local_coarsening_tolerance)
209  elem->set_refinement_flag(Elem::COARSEN);
210 
211  if (_coarsen_by_parents && parent)
212  {
213  ErrorVectorReal parent_error = error_per_parent[parent->id()];
214  if (parent_error >= 0.)
215  {
216  const Real parent_coarsening_tolerance =
217  std::sqrt(parent->n_children() *
218  local_coarsening_tolerance *
219  local_coarsening_tolerance);
220  if (parent_error < parent_coarsening_tolerance)
221  elem->set_refinement_flag(Elem::COARSEN);
222  }
223  }
224  }
225 }
226 
227 
228 
230 {
231  parallel_object_only();
232 
233  // Check for valid fractions..
234  // The fraction values must be in [0,1]
235  libmesh_assert_greater_equal (_refine_fraction, 0);
236  libmesh_assert_less_equal (_refine_fraction, 1);
237  libmesh_assert_greater_equal (_coarsen_fraction, 0);
238  libmesh_assert_less_equal (_coarsen_fraction, 1);
239 
240  // This function is currently only coded to work when coarsening by
241  // parents - it's too hard to guess how many coarsenings will be
242  // performed otherwise.
243  libmesh_assert (_coarsen_by_parents);
244 
245  // The number of active elements in the mesh - hopefully less than
246  // 2 billion on 32 bit machines
247  const dof_id_type n_active_elem = _mesh.n_active_elem();
248 
249  // The maximum number of active elements to flag for coarsening
250  const dof_id_type max_elem_coarsen =
251  static_cast<dof_id_type>(_coarsen_fraction * n_active_elem) + 1;
252 
253  // The maximum number of elements to flag for refinement
254  const dof_id_type max_elem_refine =
255  static_cast<dof_id_type>(_refine_fraction * n_active_elem) + 1;
256 
257  // Clean up the refinement flags. These could be left
258  // over from previous refinement steps.
259  this->clean_refinement_flags();
260 
261  // The target number of elements to add or remove
262  const std::ptrdiff_t n_elem_new =
263  std::ptrdiff_t(_nelem_target) - std::ptrdiff_t(n_active_elem);
264 
265  // Create an vector with active element errors and ids,
266  // sorted by highest errors first
267  const dof_id_type max_elem_id = _mesh.max_elem_id();
268  std::vector<std::pair<ErrorVectorReal, dof_id_type>> sorted_error;
269 
270  sorted_error.reserve (n_active_elem);
271 
272  // On a DistributedMesh, we need to communicate to know which remote ids
273  // correspond to active elements.
274  {
275  std::vector<bool> is_active(max_elem_id, false);
276 
277  for (auto & elem : _mesh.active_local_element_ptr_range())
278  {
279  const dof_id_type eid = elem->id();
280  is_active[eid] = true;
281  libmesh_assert_less (eid, error_per_cell.size());
282  sorted_error.push_back
283  (std::make_pair(error_per_cell[eid], eid));
284  }
285 
286  this->comm().max(is_active);
287 
288  this->comm().allgather(sorted_error);
289  }
290 
291  // Default sort works since pairs are sorted lexicographically
292  std::sort (sorted_error.begin(), sorted_error.end());
293  std::reverse (sorted_error.begin(), sorted_error.end());
294 
295  // Create a sorted error vector with coarsenable parent elements
296  // only, sorted by lowest errors first
297  ErrorVector error_per_parent;
298  std::vector<std::pair<ErrorVectorReal, dof_id_type>> sorted_parent_error;
299  Real parent_error_min, parent_error_max;
300 
301  create_parent_error_vector(error_per_cell,
302  error_per_parent,
303  parent_error_min,
304  parent_error_max);
305 
306  // create_parent_error_vector sets values for non-parents and
307  // non-coarsenable parents to -1. Get rid of them.
308  for (std::size_t i=0; i != error_per_parent.size(); ++i)
309  if (error_per_parent[i] != -1)
310  sorted_parent_error.push_back(std::make_pair(error_per_parent[i], i));
311 
312  std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
313 
314  // Keep track of how many elements we plan to coarsen & refine
315  dof_id_type coarsen_count = 0;
316  dof_id_type refine_count = 0;
317 
318  const unsigned int dim = _mesh.mesh_dimension();
319  unsigned int twotodim = 1;
320  for (unsigned int i=0; i!=dim; ++i)
321  twotodim *= 2;
322 
323  // First, let's try to get our element count to target_nelem
324  if (n_elem_new >= 0)
325  {
326  // Every element refinement creates at least
327  // 2^dim-1 new elements
328  refine_count =
329  std::min(cast_int<dof_id_type>(n_elem_new / (twotodim-1)),
330  max_elem_refine);
331  }
332  else
333  {
334  // Every successful element coarsening is likely to destroy
335  // 2^dim-1 net elements.
336  coarsen_count =
337  std::min(cast_int<dof_id_type>(-n_elem_new / (twotodim-1)),
338  max_elem_coarsen);
339  }
340 
341  // Next, let's see if we can trade any refinement for coarsening
342  while (coarsen_count < max_elem_coarsen &&
343  refine_count < max_elem_refine &&
344  coarsen_count < sorted_parent_error.size() &&
345  refine_count < sorted_error.size() &&
346  sorted_error[refine_count].first >
347  sorted_parent_error[coarsen_count].first * _coarsen_threshold)
348  {
349  coarsen_count++;
350  refine_count++;
351  }
352 
353  // On a DistributedMesh, we need to communicate to know which remote ids
354  // correspond to refinable elements
355  dof_id_type successful_refine_count = 0;
356  {
357  std::vector<bool> is_refinable(max_elem_id, false);
358 
359  for (std::size_t i=0; i != sorted_error.size(); ++i)
360  {
361  dof_id_type eid = sorted_error[i].second;
362  Elem * elem = _mesh.query_elem_ptr(eid);
363  if (elem && elem->level() < _max_h_level)
364  is_refinable[eid] = true;
365  }
366  this->comm().max(is_refinable);
367 
368  if (refine_count > max_elem_refine)
369  refine_count = max_elem_refine;
370  for (std::size_t i=0; i != sorted_error.size(); ++i)
371  {
372  if (successful_refine_count >= refine_count)
373  break;
374 
375  dof_id_type eid = sorted_error[i].second;
376  Elem * elem = _mesh.query_elem_ptr(eid);
377  if (is_refinable[eid])
378  {
379  if (elem)
381  successful_refine_count++;
382  }
383  }
384  }
385 
386  // If we couldn't refine enough elements, don't coarsen too many
387  // either
388  if (coarsen_count < (refine_count - successful_refine_count))
389  coarsen_count = 0;
390  else
391  coarsen_count -= (refine_count - successful_refine_count);
392 
393  if (coarsen_count > max_elem_coarsen)
394  coarsen_count = max_elem_coarsen;
395 
396  dof_id_type successful_coarsen_count = 0;
397  if (coarsen_count)
398  {
399  for (std::size_t i=0; i != sorted_parent_error.size(); ++i)
400  {
401  if (successful_coarsen_count >= coarsen_count * twotodim)
402  break;
403 
404  dof_id_type parent_id = sorted_parent_error[i].second;
405  Elem * parent = _mesh.query_elem_ptr(parent_id);
406 
407  // On a DistributedMesh we skip remote elements
408  if (!parent)
409  continue;
410 
411  libmesh_assert(parent->has_children());
412  for (auto & elem : parent->child_ref_range())
413  {
414  if (&elem != remote_elem)
415  {
416  libmesh_assert(elem.active());
418  successful_coarsen_count++;
419  }
420  }
421  }
422  }
423 
424  // Return true if we've done all the AMR/C we can
425  if (!successful_coarsen_count &&
426  !successful_refine_count)
427  return true;
428  // And false if there may still be more to do.
429  return false;
430 }
431 
432 
433 
435  const Real refine_frac,
436  const Real coarsen_frac,
437  const unsigned int max_l)
438 {
439  parallel_object_only();
440 
441  // The function arguments are currently just there for
442  // backwards_compatibility
444  {
445  // If the user used non-default parameters, lets warn
446  // that they're deprecated
447  if (refine_frac != 0.3 ||
448  coarsen_frac != 0.0 ||
449  max_l != libMesh::invalid_uint)
450  libmesh_deprecated();
451 
452  _refine_fraction = refine_frac;
453  _coarsen_fraction = coarsen_frac;
454  _max_h_level = max_l;
455  }
456 
457  // Check for valid fractions..
458  // The fraction values must be in [0,1]
459  libmesh_assert_greater_equal (_refine_fraction, 0);
460  libmesh_assert_less_equal (_refine_fraction, 1);
461  libmesh_assert_greater_equal (_coarsen_fraction, 0);
462  libmesh_assert_less_equal (_coarsen_fraction, 1);
463 
464  // The number of active elements in the mesh
465  const dof_id_type n_active_elem = _mesh.n_active_elem();
466 
467  // The number of elements to flag for coarsening
468  const dof_id_type n_elem_coarsen =
469  static_cast<dof_id_type>(_coarsen_fraction * n_active_elem);
470 
471  // The number of elements to flag for refinement
472  const dof_id_type n_elem_refine =
473  static_cast<dof_id_type>(_refine_fraction * n_active_elem);
474 
475 
476 
477  // Clean up the refinement flags. These could be left
478  // over from previous refinement steps.
479  this->clean_refinement_flags();
480 
481 
482  // This vector stores the error and element number for all the
483  // active elements. It will be sorted and the top & bottom
484  // elements will then be flagged for coarsening & refinement
485  std::vector<ErrorVectorReal> sorted_error;
486 
487  sorted_error.reserve (n_active_elem);
488 
489  // Loop over the active elements and create the entry
490  // in the sorted_error vector
491  for (auto & elem : _mesh.active_local_element_ptr_range())
492  sorted_error.push_back (error_per_cell[elem->id()]);
493 
494  this->comm().allgather(sorted_error);
495 
496  // Now sort the sorted_error vector
497  std::sort (sorted_error.begin(), sorted_error.end());
498 
499  // If we're coarsening by parents:
500  // Create a sorted error vector with coarsenable parent elements
501  // only, sorted by lowest errors first
502  ErrorVector error_per_parent, sorted_parent_error;
504  {
505  Real parent_error_min, parent_error_max;
506 
507  create_parent_error_vector(error_per_cell,
508  error_per_parent,
509  parent_error_min,
510  parent_error_max);
511 
512  sorted_parent_error = error_per_parent;
513  std::sort (sorted_parent_error.begin(), sorted_parent_error.end());
514 
515  // All the other error values will be 0., so get rid of them.
516  sorted_parent_error.erase (std::remove(sorted_parent_error.begin(),
517  sorted_parent_error.end(), 0.),
518  sorted_parent_error.end());
519  }
520 
521 
522  ErrorVectorReal top_error= 0., bottom_error = 0.;
523 
524  // Get the maximum error value corresponding to the
525  // bottom n_elem_coarsen elements
526  if (_coarsen_by_parents && n_elem_coarsen)
527  {
528  const unsigned int dim = _mesh.mesh_dimension();
529  unsigned int twotodim = 1;
530  for (unsigned int i=0; i!=dim; ++i)
531  twotodim *= 2;
532 
533  dof_id_type n_parent_coarsen = n_elem_coarsen / (twotodim - 1);
534 
535  if (n_parent_coarsen)
536  bottom_error = sorted_parent_error[n_parent_coarsen - 1];
537  }
538  else if (n_elem_coarsen)
539  {
540  bottom_error = sorted_error[n_elem_coarsen - 1];
541  }
542 
543  if (n_elem_refine)
544  top_error = sorted_error[sorted_error.size() - n_elem_refine];
545 
546  // Finally, let's do the element flagging
547  for (auto & elem : _mesh.active_element_ptr_range())
548  {
549  Elem * parent = elem->parent();
550 
551  if (_coarsen_by_parents && parent && n_elem_coarsen &&
552  error_per_parent[parent->id()] <= bottom_error)
554 
555  if (!_coarsen_by_parents && n_elem_coarsen &&
556  error_per_cell[elem->id()] <= bottom_error)
557  elem->set_refinement_flag(Elem::COARSEN);
558 
559  if (n_elem_refine &&
560  elem->level() < _max_h_level &&
561  error_per_cell[elem->id()] >= top_error)
562  elem->set_refinement_flag(Elem::REFINE);
563  }
564 }
565 
566 
567 
569  const Real refine_frac,
570  const Real coarsen_frac,
571  const unsigned int max_l)
572 {
573  // The function arguments are currently just there for
574  // backwards_compatibility
576  {
577  // If the user used non-default parameters, lets warn
578  // that they're deprecated
579  if (refine_frac != 0.3 ||
580  coarsen_frac != 0.0 ||
581  max_l != libMesh::invalid_uint)
582  libmesh_deprecated();
583 
584  _refine_fraction = refine_frac;
585  _coarsen_fraction = coarsen_frac;
586  _max_h_level = max_l;
587  }
588 
589  // Get the mean value from the error vector
590  const Real mean = error_per_cell.mean();
591 
592  // Get the standard deviation. This equals the
593  // square-root of the variance
594  const Real stddev = std::sqrt (error_per_cell.variance());
595 
596  // Check for valid fractions
597  libmesh_assert_greater_equal (_refine_fraction, 0);
598  libmesh_assert_less_equal (_refine_fraction, 1);
599  libmesh_assert_greater_equal (_coarsen_fraction, 0);
600  libmesh_assert_less_equal (_coarsen_fraction, 1);
601 
602  // The refine and coarsen cutoff
603  const Real refine_cutoff = mean + _refine_fraction * stddev;
604  const Real coarsen_cutoff = std::max(mean - _coarsen_fraction * stddev, 0.);
605 
606  // Loop over the elements and flag them for coarsening or
607  // refinement based on the element error
608  for (auto & elem : _mesh.active_element_ptr_range())
609  {
610  const dof_id_type id = elem->id();
611 
612  libmesh_assert_less (id, error_per_cell.size());
613 
614  const ErrorVectorReal elem_error = error_per_cell[id];
615 
616  // Possibly flag the element for coarsening ...
617  if (elem_error <= coarsen_cutoff)
618  elem->set_refinement_flag(Elem::COARSEN);
619 
620  // ... or refinement
621  if ((elem_error >= refine_cutoff) && (elem->level() < _max_h_level))
622  elem->set_refinement_flag(Elem::REFINE);
623  }
624 }
625 
626 
627 
629 {
630  element_flagging.flag_elements();
631 }
632 
633 
634 
636 {
637  for (auto & elem : _mesh.element_ptr_range())
638  {
639  if (elem->active())
640  {
641  elem->set_p_refinement_flag(elem->refinement_flag());
642  elem->set_refinement_flag(Elem::DO_NOTHING);
643  }
644  else
645  {
646  elem->set_p_refinement_flag(elem->refinement_flag());
647  elem->set_refinement_flag(Elem::INACTIVE);
648  }
649  }
650 }
651 
652 
653 
655 {
656  for (auto & elem : _mesh.element_ptr_range())
657  elem->set_p_refinement_flag(elem->refinement_flag());
658 }
659 
660 
661 
663 {
664  // Possibly clean up the refinement flags from
665  // a previous step
666  for (auto & elem : _mesh.element_ptr_range())
667  {
668  if (elem->active())
669  {
670  elem->set_refinement_flag(Elem::DO_NOTHING);
671  elem->set_p_refinement_flag(Elem::DO_NOTHING);
672  }
673  else
674  {
675  elem->set_refinement_flag(Elem::INACTIVE);
676  elem->set_p_refinement_flag(Elem::INACTIVE);
677  }
678  }
679 }
680 
681 } // namespace libMesh
682 
683 #endif
const Elem * parent() const
Definition: elem.h:2479
virtual dof_id_type n_active_elem() const =0
const unsigned int invalid_uint
Definition: libmesh.h:245
void flag_elements_by_error_tolerance(const ErrorVector &error_per_cell)
void allgather(const T &send, std::vector< T, A > &recv) const
bool flag_elements_by_nelem_target(const ErrorVector &error_per_cell)
The base class for all geometric element types.
Definition: elem.h:100
void set_refinement_flag(const RefinementState rflag)
Definition: elem.h:2646
const Parallel::Communicator & comm() const
virtual Real variance() const override
Definition: error_vector.h:115
virtual unsigned int n_children() const =0
void create_parent_error_vector(const ErrorVector &error_per_cell, ErrorVector &error_per_parent, Real &parent_error_min, Real &parent_error_max)
virtual SimpleRange< element_iterator > active_element_ptr_range()=0
long double max(long double a, double b)
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
SimpleRange< ChildRefIter > child_ref_range()
Definition: elem.h:1779
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
void flag_elements_by_mean_stddev(const ErrorVector &error_per_cell, const Real refine_fraction=1.0, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
virtual SimpleRange< element_iterator > element_ptr_range()=0
dof_id_type id() const
Definition: dof_object.h:655
virtual dof_id_type max_elem_id() const =0
void flag_elements_by(ElementFlagging &element_flagging)
void flag_elements_by_elem_fraction(const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
unsigned int level() const
Definition: elem.h:2521
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
unsigned int mesh_dimension() const
Definition: mesh_base.C:126
void flag_elements_by_error_fraction(const ErrorVector &error_per_cell, const Real refine_fraction=0.3, const Real coarsen_fraction=0.0, const unsigned int max_level=libMesh::invalid_uint)
long double min(long double a, double b)
bool has_children() const
Definition: elem.h:2428
uint8_t dof_id_type
Definition: id_types.h:64
virtual Real mean() const override
Definition: error_vector.C:69
const RemoteElem * remote_elem
Definition: remote_elem.C:57