$extrastylesheet
elem_refinement.C
Go to the documentation of this file.
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