$extrastylesheet
00001 00002 // The libMesh Finite Element Library. 00003 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00004 00005 // This library is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public 00007 // License as published by the Free Software Foundation; either 00008 // version 2.1 of the License, or (at your option) any later version. 00009 00010 // This library is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // Lesser General Public License for more details. 00014 00015 // You should have received a copy of the GNU Lesser General Public 00016 // License along with this library; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 00020 00021 // Local includes 00022 #include "libmesh/libmesh_config.h" 00023 00024 // only compile these functions if the user requests AMR support 00025 #ifdef LIBMESH_ENABLE_AMR 00026 00027 // C++ includes 00028 #include <algorithm> // for std::sort 00029 00030 // Local includes 00031 #include "libmesh/elem.h" 00032 #include "libmesh/error_vector.h" 00033 #include "libmesh/mesh_refinement.h" 00034 #include "libmesh/mesh_base.h" 00035 #include "libmesh/parallel.h" 00036 #include "libmesh/remote_elem.h" 00037 00038 namespace libMesh 00039 { 00040 00041 00042 00043 //----------------------------------------------------------------- 00044 // Mesh refinement methods 00045 void MeshRefinement::flag_elements_by_error_fraction (const ErrorVector& error_per_cell, 00046 const Real refine_frac, 00047 const Real coarsen_frac, 00048 const unsigned int max_l) 00049 { 00050 parallel_object_only(); 00051 00052 // The function arguments are currently just there for 00053 // backwards_compatibility 00054 if (!_use_member_parameters) 00055 { 00056 // If the user used non-default parameters, lets warn 00057 // that they're deprecated 00058 if (refine_frac != 0.3 || 00059 coarsen_frac != 0.0 || 00060 max_l != libMesh::invalid_uint) 00061 libmesh_deprecated(); 00062 00063 _refine_fraction = refine_frac; 00064 _coarsen_fraction = coarsen_frac; 00065 _max_h_level = max_l; 00066 } 00067 00068 // Check for valid fractions.. 00069 // The fraction values must be in [0,1] 00070 libmesh_assert_greater_equal (_refine_fraction, 0); 00071 libmesh_assert_less_equal (_refine_fraction, 1); 00072 libmesh_assert_greater_equal (_coarsen_fraction, 0); 00073 libmesh_assert_less_equal (_coarsen_fraction, 1); 00074 00075 // Clean up the refinement flags. These could be left 00076 // over from previous refinement steps. 00077 this->clean_refinement_flags(); 00078 00079 // We're getting the minimum and maximum error values 00080 // for the ACTIVE elements 00081 Real error_min = 1.e30; 00082 Real error_max = 0.; 00083 00084 // And, if necessary, for their parents 00085 Real parent_error_min = 1.e30; 00086 Real parent_error_max = 0.; 00087 00088 // Prepare another error vector if we need to sum parent errors 00089 ErrorVector error_per_parent; 00090 if (_coarsen_by_parents) 00091 { 00092 create_parent_error_vector(error_per_cell, 00093 error_per_parent, 00094 parent_error_min, 00095 parent_error_max); 00096 } 00097 00098 // We need to loop over all active elements to find the minimum 00099 MeshBase::element_iterator el_it = 00100 _mesh.active_local_elements_begin(); 00101 const MeshBase::element_iterator el_end = 00102 _mesh.active_local_elements_end(); 00103 00104 for (; el_it != el_end; ++el_it) 00105 { 00106 const dof_id_type id = (*el_it)->id(); 00107 libmesh_assert_less (id, error_per_cell.size()); 00108 00109 error_max = std::max (error_max, error_per_cell[id]); 00110 error_min = std::min (error_min, error_per_cell[id]); 00111 } 00112 this->comm().max(error_max); 00113 this->comm().min(error_min); 00114 00115 // Compute the cutoff values for coarsening and refinement 00116 const Real error_delta = (error_max - error_min); 00117 const Real parent_error_delta = parent_error_max - parent_error_min; 00118 00119 const Real refine_cutoff = (1.- _refine_fraction)*error_max; 00120 const Real coarsen_cutoff = _coarsen_fraction*error_delta + error_min; 00121 const Real parent_cutoff = _coarsen_fraction*parent_error_delta + error_min; 00122 00123 // // Print information about the error 00124 // libMesh::out << " Error Information:" << std::endl 00125 // << " ------------------" << std::endl 00126 // << " min: " << error_min << std::endl 00127 // << " max: " << error_max << std::endl 00128 // << " delta: " << error_delta << std::endl 00129 // << " refine_cutoff: " << refine_cutoff << std::endl 00130 // << " coarsen_cutoff: " << coarsen_cutoff << std::endl; 00131 00132 00133 00134 // Loop over the elements and flag them for coarsening or 00135 // refinement based on the element error 00136 00137 MeshBase::element_iterator e_it = 00138 _mesh.active_elements_begin(); 00139 const MeshBase::element_iterator e_end = 00140 _mesh.active_elements_end(); 00141 for (; e_it != e_end; ++e_it) 00142 { 00143 Elem* elem = *e_it; 00144 const dof_id_type id = elem->id(); 00145 00146 libmesh_assert_less (id, error_per_cell.size()); 00147 00148 const ErrorVectorReal elem_error = error_per_cell[id]; 00149 00150 if (_coarsen_by_parents) 00151 { 00152 Elem* parent = elem->parent(); 00153 if (parent) 00154 { 00155 const dof_id_type parentid = parent->id(); 00156 if (error_per_parent[parentid] >= 0. && 00157 error_per_parent[parentid] <= parent_cutoff) 00158 elem->set_refinement_flag(Elem::COARSEN); 00159 } 00160 } 00161 // Flag the element for coarsening if its error 00162 // is <= coarsen_fraction*delta + error_min 00163 else if (elem_error <= coarsen_cutoff) 00164 { 00165 elem->set_refinement_flag(Elem::COARSEN); 00166 } 00167 00168 // Flag the element for refinement if its error 00169 // is >= refinement_cutoff. 00170 if (elem_error >= refine_cutoff) 00171 if (elem->level() < _max_h_level) 00172 elem->set_refinement_flag(Elem::REFINE); 00173 } 00174 } 00175 00176 00177 00178 void MeshRefinement::flag_elements_by_error_tolerance (const ErrorVector& error_per_cell_in) 00179 { 00180 parallel_object_only(); 00181 00182 libmesh_assert_greater (_coarsen_threshold, 0); 00183 00184 // Check for valid fractions.. 00185 // The fraction values must be in [0,1] 00186 libmesh_assert_greater_equal (_refine_fraction, 0); 00187 libmesh_assert_less_equal (_refine_fraction, 1); 00188 libmesh_assert_greater_equal (_coarsen_fraction, 0); 00189 libmesh_assert_less_equal (_coarsen_fraction, 1); 00190 00191 // How much error per cell will we tolerate? 00192 const Real local_refinement_tolerance = 00193 _absolute_global_tolerance / std::sqrt(static_cast<Real>(_mesh.n_active_elem())); 00194 const Real local_coarsening_tolerance = 00195 local_refinement_tolerance * _coarsen_threshold; 00196 00197 // Prepare another error vector if we need to sum parent errors 00198 ErrorVector error_per_parent; 00199 if (_coarsen_by_parents) 00200 { 00201 Real parent_error_min, parent_error_max; 00202 00203 create_parent_error_vector(error_per_cell_in, 00204 error_per_parent, 00205 parent_error_min, 00206 parent_error_max); 00207 } 00208 00209 MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); 00210 const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); 00211 00212 for (; elem_it != elem_end; ++elem_it) 00213 { 00214 Elem* elem = *elem_it; 00215 Elem* parent = elem->parent(); 00216 const dof_id_type elem_number = elem->id(); 00217 const ErrorVectorReal elem_error = error_per_cell_in[elem_number]; 00218 00219 if (elem_error > local_refinement_tolerance && 00220 elem->level() < _max_h_level) 00221 elem->set_refinement_flag(Elem::REFINE); 00222 00223 if (!_coarsen_by_parents && elem_error < 00224 local_coarsening_tolerance) 00225 elem->set_refinement_flag(Elem::COARSEN); 00226 00227 if (_coarsen_by_parents && parent) 00228 { 00229 ErrorVectorReal parent_error = error_per_parent[parent->id()]; 00230 if (parent_error >= 0.) 00231 { 00232 const Real parent_coarsening_tolerance = 00233 std::sqrt(parent->n_children() * 00234 local_coarsening_tolerance * 00235 local_coarsening_tolerance); 00236 if (parent_error < parent_coarsening_tolerance) 00237 elem->set_refinement_flag(Elem::COARSEN); 00238 } 00239 } 00240 } 00241 } 00242 00243 00244 00245 bool MeshRefinement::flag_elements_by_nelem_target (const ErrorVector& error_per_cell) 00246 { 00247 parallel_object_only(); 00248 00249 // Check for valid fractions.. 00250 // The fraction values must be in [0,1] 00251 libmesh_assert_greater_equal (_refine_fraction, 0); 00252 libmesh_assert_less_equal (_refine_fraction, 1); 00253 libmesh_assert_greater_equal (_coarsen_fraction, 0); 00254 libmesh_assert_less_equal (_coarsen_fraction, 1); 00255 00256 // This function is currently only coded to work when coarsening by 00257 // parents - it's too hard to guess how many coarsenings will be 00258 // performed otherwise. 00259 libmesh_assert (_coarsen_by_parents); 00260 00261 // The number of active elements in the mesh - hopefully less than 00262 // 2 billion on 32 bit machines 00263 const dof_id_type n_active_elem = _mesh.n_active_elem(); 00264 00265 // The maximum number of active elements to flag for coarsening 00266 const dof_id_type max_elem_coarsen = 00267 static_cast<dof_id_type>(_coarsen_fraction * n_active_elem) + 1; 00268 00269 // The maximum number of elements to flag for refinement 00270 const dof_id_type max_elem_refine = 00271 static_cast<dof_id_type>(_refine_fraction * n_active_elem) + 1; 00272 00273 // Clean up the refinement flags. These could be left 00274 // over from previous refinement steps. 00275 this->clean_refinement_flags(); 00276 00277 // The target number of elements to add or remove 00278 const std::ptrdiff_t n_elem_new = _nelem_target - n_active_elem; 00279 00280 // Create an vector with active element errors and ids, 00281 // sorted by highest errors first 00282 const dof_id_type max_elem_id = _mesh.max_elem_id(); 00283 std::vector<std::pair<ErrorVectorReal, dof_id_type> > sorted_error; 00284 00285 sorted_error.reserve (n_active_elem); 00286 00287 // On a ParallelMesh, we need to communicate to know which remote ids 00288 // correspond to active elements. 00289 { 00290 std::vector<bool> is_active(max_elem_id, false); 00291 00292 MeshBase::element_iterator elem_it = _mesh.active_local_elements_begin(); 00293 const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end(); 00294 for (; elem_it != elem_end; ++elem_it) 00295 { 00296 const dof_id_type eid = (*elem_it)->id(); 00297 is_active[eid] = true; 00298 libmesh_assert_less (eid, error_per_cell.size()); 00299 sorted_error.push_back 00300 (std::make_pair(error_per_cell[eid], eid)); 00301 } 00302 00303 this->comm().max(is_active); 00304 00305 this->comm().allgather(sorted_error); 00306 } 00307 00308 // Default sort works since pairs are sorted lexicographically 00309 std::sort (sorted_error.begin(), sorted_error.end()); 00310 std::reverse (sorted_error.begin(), sorted_error.end()); 00311 00312 // Create a sorted error vector with coarsenable parent elements 00313 // only, sorted by lowest errors first 00314 ErrorVector error_per_parent; 00315 std::vector<std::pair<ErrorVectorReal, dof_id_type> > sorted_parent_error; 00316 Real parent_error_min, parent_error_max; 00317 00318 create_parent_error_vector(error_per_cell, 00319 error_per_parent, 00320 parent_error_min, 00321 parent_error_max); 00322 00323 // create_parent_error_vector sets values for non-parents and 00324 // non-coarsenable parents to -1. Get rid of them. 00325 for (dof_id_type i=0; i != error_per_parent.size(); ++i) 00326 if (error_per_parent[i] != -1) 00327 sorted_parent_error.push_back(std::make_pair(error_per_parent[i], i)); 00328 00329 std::sort (sorted_parent_error.begin(), sorted_parent_error.end()); 00330 00331 // Keep track of how many elements we plan to coarsen & refine 00332 dof_id_type coarsen_count = 0; 00333 dof_id_type refine_count = 0; 00334 00335 const unsigned int dim = _mesh.mesh_dimension(); 00336 unsigned int twotodim = 1; 00337 for (unsigned int i=0; i!=dim; ++i) 00338 twotodim *= 2; 00339 00340 // First, let's try to get our element count to target_nelem 00341 if (n_elem_new >= 0) 00342 { 00343 // Every element refinement creates at least 00344 // 2^dim-1 new elements 00345 refine_count = 00346 std::min(cast_int<dof_id_type>(n_elem_new / (twotodim-1)), 00347 max_elem_refine); 00348 } 00349 else 00350 { 00351 // Every successful element coarsening is likely to destroy 00352 // 2^dim-1 net elements. 00353 coarsen_count = 00354 std::min(cast_int<dof_id_type>(-n_elem_new / (twotodim-1)), 00355 max_elem_coarsen); 00356 } 00357 00358 // Next, let's see if we can trade any refinement for coarsening 00359 while (coarsen_count < max_elem_coarsen && 00360 refine_count < max_elem_refine && 00361 coarsen_count < sorted_parent_error.size() && 00362 refine_count < sorted_error.size() && 00363 sorted_error[refine_count].first > 00364 sorted_parent_error[coarsen_count].first * _coarsen_threshold) 00365 { 00366 coarsen_count++; 00367 refine_count++; 00368 } 00369 00370 // On a ParallelMesh, we need to communicate to know which remote ids 00371 // correspond to refinable elements 00372 dof_id_type successful_refine_count = 0; 00373 { 00374 std::vector<bool> is_refinable(max_elem_id, false); 00375 00376 for (dof_id_type i=0; i != sorted_error.size(); ++i) 00377 { 00378 dof_id_type eid = sorted_error[i].second; 00379 Elem *elem = _mesh.query_elem(eid); 00380 if (elem && elem->level() < _max_h_level) 00381 is_refinable[eid] = true; 00382 } 00383 this->comm().max(is_refinable); 00384 00385 if (refine_count > max_elem_refine) 00386 refine_count = max_elem_refine; 00387 for (dof_id_type i=0; i != sorted_error.size(); ++i) 00388 { 00389 if (successful_refine_count >= refine_count) 00390 break; 00391 00392 dof_id_type eid = sorted_error[i].second; 00393 Elem *elem = _mesh.query_elem(eid); 00394 if (is_refinable[eid]) 00395 { 00396 if (elem) 00397 elem->set_refinement_flag(Elem::REFINE); 00398 successful_refine_count++; 00399 } 00400 } 00401 } 00402 00403 // If we couldn't refine enough elements, don't coarsen too many 00404 // either 00405 if (coarsen_count < (refine_count - successful_refine_count)) 00406 coarsen_count = 0; 00407 else 00408 coarsen_count -= (refine_count - successful_refine_count); 00409 00410 if (coarsen_count > max_elem_coarsen) 00411 coarsen_count = max_elem_coarsen; 00412 00413 dof_id_type successful_coarsen_count = 0; 00414 if (coarsen_count) 00415 { 00416 for (dof_id_type i=0; i != sorted_parent_error.size(); ++i) 00417 { 00418 if (successful_coarsen_count >= coarsen_count * twotodim) 00419 break; 00420 00421 dof_id_type parent_id = sorted_parent_error[i].second; 00422 Elem *parent = _mesh.query_elem(parent_id); 00423 00424 // On a ParallelMesh we skip remote elements 00425 if (!parent) 00426 continue; 00427 00428 libmesh_assert(parent->has_children()); 00429 for (unsigned int c=0; c != parent->n_children(); ++c) 00430 { 00431 Elem *elem = parent->child(c); 00432 if (elem && elem != remote_elem) 00433 { 00434 libmesh_assert(elem->active()); 00435 elem->set_refinement_flag(Elem::COARSEN); 00436 successful_coarsen_count++; 00437 } 00438 } 00439 } 00440 } 00441 00442 // Return true if we've done all the AMR/C we can 00443 if (!successful_coarsen_count && 00444 !successful_refine_count) 00445 return true; 00446 // And false if there may still be more to do. 00447 return false; 00448 } 00449 00450 00451 00452 void MeshRefinement::flag_elements_by_elem_fraction (const ErrorVector& error_per_cell, 00453 const Real refine_frac, 00454 const Real coarsen_frac, 00455 const unsigned int max_l) 00456 { 00457 parallel_object_only(); 00458 00459 // The function arguments are currently just there for 00460 // backwards_compatibility 00461 if (!_use_member_parameters) 00462 { 00463 // If the user used non-default parameters, lets warn 00464 // that they're deprecated 00465 if (refine_frac != 0.3 || 00466 coarsen_frac != 0.0 || 00467 max_l != libMesh::invalid_uint) 00468 libmesh_deprecated(); 00469 00470 _refine_fraction = refine_frac; 00471 _coarsen_fraction = coarsen_frac; 00472 _max_h_level = max_l; 00473 } 00474 00475 // Check for valid fractions.. 00476 // The fraction values must be in [0,1] 00477 libmesh_assert_greater_equal (_refine_fraction, 0); 00478 libmesh_assert_less_equal (_refine_fraction, 1); 00479 libmesh_assert_greater_equal (_coarsen_fraction, 0); 00480 libmesh_assert_less_equal (_coarsen_fraction, 1); 00481 00482 // The number of active elements in the mesh 00483 const dof_id_type n_active_elem = _mesh.n_elem(); 00484 00485 // The number of elements to flag for coarsening 00486 const dof_id_type n_elem_coarsen = 00487 static_cast<dof_id_type>(_coarsen_fraction * n_active_elem); 00488 00489 // The number of elements to flag for refinement 00490 const dof_id_type n_elem_refine = 00491 static_cast<dof_id_type>(_refine_fraction * n_active_elem); 00492 00493 00494 00495 // Clean up the refinement flags. These could be left 00496 // over from previous refinement steps. 00497 this->clean_refinement_flags(); 00498 00499 00500 // This vector stores the error and element number for all the 00501 // active elements. It will be sorted and the top & bottom 00502 // elements will then be flagged for coarsening & refinement 00503 std::vector<ErrorVectorReal> sorted_error; 00504 00505 sorted_error.reserve (n_active_elem); 00506 00507 // Loop over the active elements and create the entry 00508 // in the sorted_error vector 00509 MeshBase::element_iterator elem_it = _mesh.active_local_elements_begin(); 00510 const MeshBase::element_iterator elem_end = _mesh.active_local_elements_end(); 00511 00512 for (; elem_it != elem_end; ++elem_it) 00513 sorted_error.push_back (error_per_cell[(*elem_it)->id()]); 00514 00515 this->comm().allgather(sorted_error); 00516 00517 // Now sort the sorted_error vector 00518 std::sort (sorted_error.begin(), sorted_error.end()); 00519 00520 // If we're coarsening by parents: 00521 // Create a sorted error vector with coarsenable parent elements 00522 // only, sorted by lowest errors first 00523 ErrorVector error_per_parent, sorted_parent_error; 00524 if (_coarsen_by_parents) 00525 { 00526 Real parent_error_min, parent_error_max; 00527 00528 create_parent_error_vector(error_per_cell, 00529 error_per_parent, 00530 parent_error_min, 00531 parent_error_max); 00532 00533 sorted_parent_error = error_per_parent; 00534 std::sort (sorted_parent_error.begin(), sorted_parent_error.end()); 00535 00536 // All the other error values will be 0., so get rid of them. 00537 sorted_parent_error.erase (std::remove(sorted_parent_error.begin(), 00538 sorted_parent_error.end(), 0.), 00539 sorted_parent_error.end()); 00540 } 00541 00542 00543 ErrorVectorReal top_error= 0., bottom_error = 0.; 00544 00545 // Get the maximum error value corresponding to the 00546 // bottom n_elem_coarsen elements 00547 if (_coarsen_by_parents && n_elem_coarsen) 00548 { 00549 const unsigned int dim = _mesh.mesh_dimension(); 00550 unsigned int twotodim = 1; 00551 for (unsigned int i=0; i!=dim; ++i) 00552 twotodim *= 2; 00553 00554 dof_id_type n_parent_coarsen = n_elem_coarsen / (twotodim - 1); 00555 00556 if (n_parent_coarsen) 00557 bottom_error = sorted_parent_error[n_parent_coarsen - 1]; 00558 } 00559 else if (n_elem_coarsen) 00560 { 00561 bottom_error = sorted_error[n_elem_coarsen - 1]; 00562 } 00563 00564 if (n_elem_refine) 00565 top_error = sorted_error[sorted_error.size() - n_elem_refine]; 00566 00567 // Finally, let's do the element flagging 00568 elem_it = _mesh.active_elements_begin(); 00569 for (; elem_it != elem_end; ++elem_it) 00570 { 00571 Elem* elem = *elem_it; 00572 Elem* parent = elem->parent(); 00573 00574 if (_coarsen_by_parents && parent && n_elem_coarsen && 00575 error_per_parent[parent->id()] <= bottom_error) 00576 elem->set_refinement_flag(Elem::COARSEN); 00577 00578 if (!_coarsen_by_parents && n_elem_coarsen && 00579 error_per_cell[elem->id()] <= bottom_error) 00580 elem->set_refinement_flag(Elem::COARSEN); 00581 00582 if (n_elem_refine && 00583 elem->level() < _max_h_level && 00584 error_per_cell[elem->id()] >= top_error) 00585 elem->set_refinement_flag(Elem::REFINE); 00586 } 00587 } 00588 00589 00590 00591 void MeshRefinement::flag_elements_by_mean_stddev (const ErrorVector& error_per_cell, 00592 const Real refine_frac, 00593 const Real coarsen_frac, 00594 const unsigned int max_l) 00595 { 00596 // The function arguments are currently just there for 00597 // backwards_compatibility 00598 if (!_use_member_parameters) 00599 { 00600 // If the user used non-default parameters, lets warn 00601 // that they're deprecated 00602 if (refine_frac != 0.3 || 00603 coarsen_frac != 0.0 || 00604 max_l != libMesh::invalid_uint) 00605 libmesh_deprecated(); 00606 00607 _refine_fraction = refine_frac; 00608 _coarsen_fraction = coarsen_frac; 00609 _max_h_level = max_l; 00610 } 00611 00612 // Get the mean value from the error vector 00613 const Real mean = error_per_cell.mean(); 00614 00615 // Get the standard deviation. This equals the 00616 // square-root of the variance 00617 const Real stddev = std::sqrt (error_per_cell.variance()); 00618 00619 // Check for valid fractions 00620 libmesh_assert_greater_equal (_refine_fraction, 0); 00621 libmesh_assert_less_equal (_refine_fraction, 1); 00622 libmesh_assert_greater_equal (_coarsen_fraction, 0); 00623 libmesh_assert_less_equal (_coarsen_fraction, 1); 00624 00625 // The refine and coarsen cutoff 00626 const Real refine_cutoff = mean + _refine_fraction * stddev; 00627 const Real coarsen_cutoff = std::max(mean - _coarsen_fraction * stddev, 0.); 00628 00629 // Loop over the elements and flag them for coarsening or 00630 // refinement based on the element error 00631 MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); 00632 const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); 00633 00634 for (; elem_it != elem_end; ++elem_it) 00635 { 00636 Elem* elem = *elem_it; 00637 const dof_id_type id = elem->id(); 00638 00639 libmesh_assert_less (id, error_per_cell.size()); 00640 00641 const ErrorVectorReal elem_error = error_per_cell[id]; 00642 00643 // Possibly flag the element for coarsening ... 00644 if (elem_error <= coarsen_cutoff) 00645 elem->set_refinement_flag(Elem::COARSEN); 00646 00647 // ... or refinement 00648 if ((elem_error >= refine_cutoff) && (elem->level() < _max_h_level)) 00649 elem->set_refinement_flag(Elem::REFINE); 00650 } 00651 } 00652 00653 00654 00655 void MeshRefinement::flag_elements_by (ElementFlagging &element_flagging) 00656 { 00657 element_flagging.flag_elements(); 00658 } 00659 00660 00661 00662 void MeshRefinement::switch_h_to_p_refinement () 00663 { 00664 MeshBase::element_iterator elem_it = _mesh.elements_begin(); 00665 const MeshBase::element_iterator elem_end = _mesh.elements_end(); 00666 00667 for ( ; elem_it != elem_end; ++elem_it) 00668 { 00669 if ((*elem_it)->active()) 00670 { 00671 (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag()); 00672 (*elem_it)->set_refinement_flag(Elem::DO_NOTHING); 00673 } 00674 else 00675 { 00676 (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag()); 00677 (*elem_it)->set_refinement_flag(Elem::INACTIVE); 00678 } 00679 } 00680 } 00681 00682 00683 00684 void MeshRefinement::add_p_to_h_refinement () 00685 { 00686 MeshBase::element_iterator elem_it = _mesh.elements_begin(); 00687 const MeshBase::element_iterator elem_end = _mesh.elements_end(); 00688 00689 for ( ; elem_it != elem_end; ++elem_it) 00690 (*elem_it)->set_p_refinement_flag((*elem_it)->refinement_flag()); 00691 } 00692 00693 00694 00695 void MeshRefinement::clean_refinement_flags () 00696 { 00697 // Possibly clean up the refinement flags from 00698 // a previous step 00699 // elem_iterator elem_it (_mesh.elements_begin()); 00700 // const elem_iterator elem_end(_mesh.elements_end()); 00701 00702 MeshBase::element_iterator elem_it = _mesh.elements_begin(); 00703 const MeshBase::element_iterator elem_end = _mesh.elements_end(); 00704 00705 for ( ; elem_it != elem_end; ++elem_it) 00706 { 00707 if ((*elem_it)->active()) 00708 { 00709 (*elem_it)->set_refinement_flag(Elem::DO_NOTHING); 00710 (*elem_it)->set_p_refinement_flag(Elem::DO_NOTHING); 00711 } 00712 else 00713 { 00714 (*elem_it)->set_refinement_flag(Elem::INACTIVE); 00715 (*elem_it)->set_p_refinement_flag(Elem::INACTIVE); 00716 } 00717 } 00718 } 00719 00720 } // namespace libMesh 00721 00722 #endif