$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 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 // C++ includes 00021 00022 // Local includes 00023 #include "libmesh/elem.h" 00024 #include "libmesh/mesh_refinement.h" 00025 #include "libmesh/remote_elem.h" 00026 00027 namespace libMesh 00028 { 00029 00030 00031 //-------------------------------------------------------------------- 00032 // Elem methods 00033 00039 #ifdef LIBMESH_ENABLE_AMR 00040 00041 void Elem::refine (MeshRefinement& mesh_refinement) 00042 { 00043 libmesh_assert_equal_to (this->refinement_flag(), Elem::REFINE); 00044 libmesh_assert (this->active()); 00045 00046 // Create my children if necessary 00047 if (!_children) 00048 { 00049 _children = new Elem*[this->n_children()]; 00050 00051 unsigned int parent_p_level = this->p_level(); 00052 for (unsigned int c=0; c<this->n_children(); c++) 00053 { 00054 _children[c] = Elem::build(this->type(), this).release(); 00055 _children[c]->set_refinement_flag(Elem::JUST_REFINED); 00056 _children[c]->set_p_level(parent_p_level); 00057 _children[c]->set_p_refinement_flag(this->p_refinement_flag()); 00058 } 00059 00060 // Compute new nodal locations 00061 // and asssign nodes to children 00062 // Make these static. It is unlikely the 00063 // sizes will change from call to call, so having these 00064 // static should save on reallocations 00065 std::vector<std::vector<Point> > p (this->n_children()); 00066 std::vector<std::vector<Node*> > nodes(this->n_children()); 00067 00068 00069 // compute new nodal locations 00070 for (unsigned int c=0; c<this->n_children(); c++) 00071 { 00072 Elem *current_child = this->child(c); 00073 p[c].resize (current_child->n_nodes()); 00074 nodes[c].resize(current_child->n_nodes()); 00075 00076 for (unsigned int nc=0; nc<current_child->n_nodes(); nc++) 00077 { 00078 // zero entries 00079 p[c][nc].zero(); 00080 nodes[c][nc] = NULL; 00081 00082 for (unsigned int n=0; n<this->n_nodes(); n++) 00083 { 00084 // The value from the embedding matrix 00085 const float em_val = this->embedding_matrix(c,nc,n); 00086 00087 if (em_val != 0.) 00088 { 00089 p[c][nc].add_scaled (this->point(n), em_val); 00090 00091 // We may have found the node, in which case we 00092 // won't need to look it up later. 00093 if (em_val == 1.) 00094 nodes[c][nc] = this->get_node(n); 00095 } 00096 } 00097 } 00098 00099 // assign nodes to children & add them to the mesh 00100 const Real pointtol = this->hmin() * TOLERANCE; 00101 for (unsigned int nc=0; nc<current_child->n_nodes(); nc++) 00102 { 00103 if (nodes[c][nc] != NULL) 00104 { 00105 current_child->set_node(nc) = nodes[c][nc]; 00106 } 00107 else 00108 { 00109 current_child->set_node(nc) = 00110 mesh_refinement.add_point(p[c][nc], 00111 current_child->processor_id(), 00112 pointtol); 00113 current_child->get_node(nc)->set_n_systems 00114 (this->n_systems()); 00115 } 00116 } 00117 00118 mesh_refinement.add_elem (current_child); 00119 current_child->set_n_systems(this->n_systems()); 00120 } 00121 } 00122 else 00123 { 00124 unsigned int parent_p_level = this->p_level(); 00125 for (unsigned int c=0; c<this->n_children(); c++) 00126 { 00127 Elem *current_child = this->child(c); 00128 libmesh_assert(current_child->subactive()); 00129 current_child->set_refinement_flag(Elem::JUST_REFINED); 00130 current_child->set_p_level(parent_p_level); 00131 current_child->set_p_refinement_flag(this->p_refinement_flag()); 00132 } 00133 } 00134 00135 // Un-set my refinement flag now 00136 this->set_refinement_flag(Elem::INACTIVE); 00137 this->set_p_refinement_flag(Elem::INACTIVE); 00138 00139 for (unsigned int c=0; c<this->n_children(); c++) 00140 { 00141 libmesh_assert_equal_to (this->child(c)->parent(), this); 00142 libmesh_assert(this->child(c)->active()); 00143 } 00144 libmesh_assert (this->ancestor()); 00145 } 00146 00147 00148 00149 void Elem::coarsen() 00150 { 00151 libmesh_assert_equal_to (this->refinement_flag(), Elem::COARSEN_INACTIVE); 00152 libmesh_assert (!this->active()); 00153 00154 // We no longer delete children until MeshRefinement::contract() 00155 // delete [] _children; 00156 // _children = NULL; 00157 00158 unsigned int parent_p_level = 0; 00159 00160 // re-compute hanging node nodal locations 00161 for (unsigned int c=0; c<this->n_children(); c++) 00162 { 00163 Elem *mychild = this->child(c); 00164 if (mychild == remote_elem) 00165 continue; 00166 for (unsigned int nc=0; nc<mychild->n_nodes(); nc++) 00167 { 00168 Point new_pos; 00169 bool calculated_new_pos = false; 00170 00171 for (unsigned int n=0; n<this->n_nodes(); n++) 00172 { 00173 // The value from the embedding matrix 00174 const float em_val = this->embedding_matrix(c,nc,n); 00175 00176 // The node location is somewhere between existing vertices 00177 if ((em_val != 0.) && (em_val != 1.)) 00178 { 00179 new_pos.add_scaled (this->point(n), em_val); 00180 calculated_new_pos = true; 00181 } 00182 } 00183 00184 if(calculated_new_pos) 00185 { 00186 //Move the existing node back into it's original location 00187 for(unsigned int i=0; i<LIBMESH_DIM; i++) 00188 { 00189 Point & child_node = *(mychild->get_node(nc)); 00190 child_node(i)=new_pos(i); 00191 } 00192 } 00193 } 00194 } 00195 00196 for (unsigned int c=0; c<this->n_children(); c++) 00197 { 00198 Elem *mychild = this->child(c); 00199 if (mychild == remote_elem) 00200 continue; 00201 libmesh_assert_equal_to (mychild->refinement_flag(), Elem::COARSEN); 00202 mychild->set_refinement_flag(Elem::INACTIVE); 00203 if (mychild->p_level() > parent_p_level) 00204 parent_p_level = mychild->p_level(); 00205 } 00206 00207 this->set_refinement_flag(Elem::JUST_COARSENED); 00208 this->set_p_level(parent_p_level); 00209 00210 libmesh_assert (this->active()); 00211 } 00212 00213 00214 00215 void Elem::contract() 00216 { 00217 // Subactive elements get deleted entirely, not contracted 00218 libmesh_assert (this->active()); 00219 00220 // Active contracted elements no longer can have children 00221 delete [] _children; 00222 _children = NULL; 00223 00224 if (this->refinement_flag() == Elem::JUST_COARSENED) 00225 this->set_refinement_flag(Elem::DO_NOTHING); 00226 } 00227 00228 #endif // #ifdef LIBMESH_ENABLE_AMR 00229 00230 00231 } // namespace libMesh