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