mesh_refinement_smoothing.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 // Local includes 00021 #include "libmesh/libmesh_config.h" 00022 00023 // only compile these functions if the user requests AMR support 00024 #ifdef LIBMESH_ENABLE_AMR 00025 00026 #include "libmesh/elem.h" 00027 #include "libmesh/mesh_base.h" 00028 #include "libmesh/mesh_refinement.h" 00029 #include "libmesh/parallel.h" 00030 #include "libmesh/remote_elem.h" 00031 00032 namespace libMesh 00033 { 00034 00035 00036 00037 //----------------------------------------------------------------- 00038 // Mesh refinement methods 00039 bool MeshRefinement::limit_level_mismatch_at_node (const unsigned int max_mismatch) 00040 { 00041 // This function must be run on all processors at once 00042 parallel_only(); 00043 00044 bool flags_changed = false; 00045 00046 00047 // Vector holding the maximum element level that touches a node. 00048 std::vector<unsigned char> max_level_at_node (_mesh.n_nodes(), 0); 00049 std::vector<unsigned char> max_p_level_at_node (_mesh.n_nodes(), 0); 00050 00051 00052 // Loop over all the active elements & fill the vector 00053 { 00054 MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); 00055 const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); 00056 00057 for (; elem_it != elem_end; ++elem_it) 00058 { 00059 const Elem* elem = *elem_it; 00060 const unsigned char elem_level = 00061 elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0); 00062 const unsigned char elem_p_level = 00063 elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0); 00064 00065 // Set the max_level at each node 00066 for (unsigned int n=0; n<elem->n_nodes(); n++) 00067 { 00068 const dof_id_type node_number = elem->node(n); 00069 00070 libmesh_assert_less (node_number, max_level_at_node.size()); 00071 00072 max_level_at_node[node_number] = 00073 std::max (max_level_at_node[node_number], elem_level); 00074 max_p_level_at_node[node_number] = 00075 std::max (max_p_level_at_node[node_number], elem_p_level); 00076 } 00077 } 00078 } 00079 00080 00081 // Now loop over the active elements and flag the elements 00082 // who violate the requested level mismatch 00083 { 00084 MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); 00085 const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); 00086 00087 for (; elem_it != elem_end; ++elem_it) 00088 { 00089 Elem* elem = *elem_it; 00090 const unsigned int elem_level = elem->level(); 00091 const unsigned int elem_p_level = elem->p_level(); 00092 00093 // Skip the element if it is already fully flagged 00094 if (elem->refinement_flag() == Elem::REFINE && 00095 elem->p_refinement_flag() == Elem::REFINE) 00096 continue; 00097 00098 // Loop over the nodes, check for possible mismatch 00099 for (unsigned int n=0; n<elem->n_nodes(); n++) 00100 { 00101 const dof_id_type node_number = elem->node(n); 00102 00103 // Flag the element for refinement if it violates 00104 // the requested level mismatch 00105 if ( (elem_level + max_mismatch) < max_level_at_node[node_number] 00106 && elem->refinement_flag() != Elem::REFINE) 00107 { 00108 elem->set_refinement_flag (Elem::REFINE); 00109 flags_changed = true; 00110 } 00111 if ( (elem_p_level + max_mismatch) < max_p_level_at_node[node_number] 00112 && elem->p_refinement_flag() != Elem::REFINE) 00113 { 00114 elem->set_p_refinement_flag (Elem::REFINE); 00115 flags_changed = true; 00116 } 00117 } 00118 } 00119 } 00120 00121 // If flags changed on any processor then they changed globally 00122 CommWorld.max(flags_changed); 00123 00124 return flags_changed; 00125 } 00126 00127 00128 00129 //----------------------------------------------------------------- 00130 // Mesh refinement methods 00131 bool MeshRefinement::limit_level_mismatch_at_edge (const unsigned int max_mismatch) 00132 { 00133 // This function must be run on all processors at once 00134 parallel_only(); 00135 00136 bool flags_changed = false; 00137 00138 00139 // Maps holding the maximum element level that touches an edge 00140 std::map<std::pair<unsigned int, unsigned int>, unsigned char> 00141 max_level_at_edge; 00142 std::map<std::pair<unsigned int, unsigned int>, unsigned char> 00143 max_p_level_at_edge; 00144 00145 // Loop over all the active elements & fill the maps 00146 { 00147 MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); 00148 const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); 00149 00150 for (; elem_it != elem_end; ++elem_it) 00151 { 00152 const Elem* elem = *elem_it; 00153 const unsigned char elem_level = 00154 elem->level() + ((elem->refinement_flag() == Elem::REFINE) ? 1 : 0); 00155 const unsigned char elem_p_level = 00156 elem->p_level() + ((elem->p_refinement_flag() == Elem::REFINE) ? 1 : 0); 00157 00158 // Set the max_level at each edge 00159 for (unsigned int n=0; n<elem->n_edges(); n++) 00160 { 00161 AutoPtr<Elem> edge = elem->build_edge(n); 00162 dof_id_type childnode0 = edge->node(0); 00163 dof_id_type childnode1 = edge->node(1); 00164 if (childnode1 < childnode0) 00165 std::swap(childnode0, childnode1); 00166 00167 for (const Elem *p = elem; p != NULL; p = p->parent()) 00168 { 00169 AutoPtr<Elem> pedge = p->build_edge(n); 00170 dof_id_type node0 = pedge->node(0); 00171 dof_id_type node1 = pedge->node(1); 00172 00173 if (node1 < node0) 00174 std::swap(node0, node1); 00175 00176 // If elem does not share this edge with its ancestor 00177 // p, refinement levels of elements sharing p's edge 00178 // are not restricted by refinement levels of elem. 00179 // Furthermore, elem will not share this edge with any 00180 // of p's ancestors, so we can safely break out of the 00181 // for loop early. 00182 if (node0 != childnode0 && node1 != childnode1) 00183 break; 00184 00185 childnode0 = node0; 00186 childnode1 = node1; 00187 00188 std::pair<unsigned int, unsigned int> edge_key = 00189 std::make_pair(node0, node1); 00190 00191 if (max_level_at_edge.find(edge_key) == 00192 max_level_at_edge.end()) 00193 { 00194 max_level_at_edge[edge_key] = elem_level; 00195 max_p_level_at_edge[edge_key] = elem_p_level; 00196 } 00197 else 00198 { 00199 max_level_at_edge[edge_key] = 00200 std::max (max_level_at_edge[edge_key], elem_level); 00201 max_p_level_at_edge[edge_key] = 00202 std::max (max_p_level_at_edge[edge_key], elem_p_level); 00203 } 00204 } 00205 } 00206 } 00207 } 00208 00209 00210 // Now loop over the active elements and flag the elements 00211 // who violate the requested level mismatch 00212 { 00213 MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); 00214 const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); 00215 00216 for (; elem_it != elem_end; ++elem_it) 00217 { 00218 Elem* elem = *elem_it; 00219 const unsigned int elem_level = elem->level(); 00220 const unsigned int elem_p_level = elem->p_level(); 00221 00222 // Skip the element if it is already fully flagged 00223 if (elem->refinement_flag() == Elem::REFINE && 00224 elem->p_refinement_flag() == Elem::REFINE) 00225 continue; 00226 00227 // Loop over the nodes, check for possible mismatch 00228 for (unsigned int n=0; n<elem->n_edges(); n++) 00229 { 00230 AutoPtr<Elem> edge = elem->build_edge(n); 00231 dof_id_type node0 = edge->node(0); 00232 dof_id_type node1 = edge->node(1); 00233 if (node1 < node0) 00234 std::swap(node0, node1); 00235 00236 std::pair<dof_id_type, dof_id_type> edge_key = 00237 std::make_pair(node0, node1); 00238 00239 // Flag the element for refinement if it violates 00240 // the requested level mismatch 00241 if ( (elem_level + max_mismatch) < max_level_at_edge[edge_key] 00242 && elem->refinement_flag() != Elem::REFINE) 00243 { 00244 elem->set_refinement_flag (Elem::REFINE); 00245 flags_changed = true; 00246 } 00247 if ( (elem_p_level + max_mismatch) < max_p_level_at_edge[edge_key] 00248 && elem->p_refinement_flag() != Elem::REFINE) 00249 { 00250 elem->set_p_refinement_flag (Elem::REFINE); 00251 flags_changed = true; 00252 } 00253 } 00254 } 00255 } 00256 00257 // If flags changed on any processor then they changed globally 00258 CommWorld.max(flags_changed); 00259 00260 return flags_changed; 00261 } 00262 00263 00264 00265 00266 bool MeshRefinement::eliminate_unrefined_patches () 00267 { 00268 // This function must be run on all processors at once 00269 parallel_only(); 00270 00271 bool flags_changed = false; 00272 00273 MeshBase::element_iterator elem_it = _mesh.active_elements_begin(); 00274 const MeshBase::element_iterator elem_end = _mesh.active_elements_end(); 00275 00276 for (; elem_it != elem_end; ++elem_it) 00277 { 00278 Elem* elem = *elem_it; 00279 // First assume that we'll have to flag this element for both h 00280 // and p refinement, then change our minds if we see any 00281 // neighbors that are as coarse or coarser than us. 00282 bool h_flag_me = true, 00283 p_flag_me = true; 00284 00285 00286 // Skip the element if it is already fully flagged for refinement 00287 if (elem->p_refinement_flag() == Elem::REFINE) 00288 p_flag_me = false; 00289 if (elem->refinement_flag() == Elem::REFINE) 00290 { 00291 h_flag_me = false; 00292 if (!p_flag_me) 00293 continue; 00294 } 00295 // Test the parent if that is already flagged for coarsening 00296 else if (elem->refinement_flag() == Elem::COARSEN) 00297 { 00298 libmesh_assert(elem->parent()); 00299 elem = elem->parent(); 00300 // FIXME - this doesn't seem right - RHS 00301 if (elem->refinement_flag() != Elem::COARSEN_INACTIVE) 00302 continue; 00303 p_flag_me = false; 00304 } 00305 00306 const unsigned int my_level = elem->level(); 00307 int my_p_adjustment = 0; 00308 if (elem->p_refinement_flag() == Elem::REFINE) 00309 my_p_adjustment = 1; 00310 else if (elem->p_refinement_flag() == Elem::COARSEN) 00311 { 00312 libmesh_assert_greater (elem->p_level(), 0); 00313 my_p_adjustment = -1; 00314 } 00315 const unsigned int my_new_p_level = elem->p_level() + 00316 my_p_adjustment; 00317 00318 // Check all the element neighbors 00319 for (unsigned int n=0; n<elem->n_neighbors(); n++) 00320 { 00321 const Elem *neighbor = elem->neighbor(n); 00322 // Quit if the element is on a local boundary 00323 if (neighbor == NULL || neighbor == remote_elem) 00324 { 00325 h_flag_me = false; 00326 p_flag_me = false; 00327 break; 00328 } 00329 // if the neighbor will be equally or less refined than 00330 // we are, then we will not become an unrefined island. 00331 // So if we are still considering h refinement: 00332 if (h_flag_me && 00333 // If our neighbor is already at a lower level, 00334 // it can't end up at a higher level even if it 00335 // is flagged for refinement once 00336 ((neighbor->level() < my_level) || 00337 // If our neighbor is at the same level but isn't 00338 // flagged for refinement, it won't end up at a 00339 // higher level 00340 ((neighbor->active()) && 00341 (neighbor->refinement_flag() != Elem::REFINE)) || 00342 // If our neighbor is currently more refined but is 00343 // a parent flagged for coarsening, it will end up 00344 // at the same level. 00345 (neighbor->refinement_flag() == Elem::COARSEN_INACTIVE))) 00346 { 00347 // We've proven we won't become an unrefined island, 00348 // so don't h refine to avoid that. 00349 h_flag_me = false; 00350 00351 // If we've also proven we don't need to p refine, 00352 // we don't need to check more neighbors 00353 if (!p_flag_me) 00354 break; 00355 } 00356 if (p_flag_me) 00357 { 00358 // if active neighbors will have a p level 00359 // equal to or lower than ours, then we do not need to p 00360 // refine ourselves. 00361 if (neighbor->active()) 00362 { 00363 int p_adjustment = 0; 00364 if (neighbor->p_refinement_flag() == Elem::REFINE) 00365 p_adjustment = 1; 00366 else if (neighbor->p_refinement_flag() == Elem::COARSEN) 00367 { 00368 libmesh_assert_greater (neighbor->p_level(), 0); 00369 p_adjustment = -1; 00370 } 00371 if (my_new_p_level >= neighbor->p_level() + p_adjustment) 00372 { 00373 p_flag_me = false; 00374 if (!h_flag_me) 00375 break; 00376 } 00377 } 00378 // If we have inactive neighbors, we need to 00379 // test all their active descendants which neighbor us 00380 else if (neighbor->ancestor()) 00381 { 00382 if (neighbor->min_new_p_level_by_neighbor(elem, 00383 my_new_p_level + 2) <= my_new_p_level) 00384 { 00385 p_flag_me = false; 00386 if (!h_flag_me) 00387 break; 00388 } 00389 } 00390 } 00391 } 00392 00393 if (h_flag_me) 00394 { 00395 // Parents that would create islands should no longer 00396 // coarsen 00397 if (elem->refinement_flag() == Elem::COARSEN_INACTIVE) 00398 { 00399 for (unsigned int c=0; c<elem->n_children(); c++) 00400 { 00401 libmesh_assert_equal_to (elem->child(c)->refinement_flag(), 00402 Elem::COARSEN); 00403 elem->child(c)->set_refinement_flag(Elem::DO_NOTHING); 00404 } 00405 elem->set_refinement_flag(Elem::INACTIVE); 00406 } 00407 else 00408 elem->set_refinement_flag(Elem::REFINE); 00409 flags_changed = true; 00410 } 00411 if (p_flag_me) 00412 { 00413 if (elem->p_refinement_flag() == Elem::COARSEN) 00414 elem->set_p_refinement_flag(Elem::DO_NOTHING); 00415 else 00416 elem->set_p_refinement_flag(Elem::REFINE); 00417 flags_changed = true; 00418 } 00419 } 00420 00421 // If flags changed on any processor then they changed globally 00422 CommWorld.max(flags_changed); 00423 00424 return flags_changed; 00425 } 00426 00427 } // namespace libMesh 00428 00429 00430 #endif
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: