LCOV - code coverage report
Current view: top level - src/geom - elem_refinement.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4475 (55045b) with base a68cc6 Lines: 102 103 99.0 %
Date: 2026-06-03 14:29:06 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 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             : // C++ includes
      21             : 
      22             : // Local includes
      23             : #include "libmesh/elem.h"
      24             : #include "libmesh/mesh_refinement.h"
      25             : #include "libmesh/remote_elem.h"
      26             : 
      27             : namespace libMesh
      28             : {
      29             : 
      30             : 
      31             : //--------------------------------------------------------------------
      32             : // Elem methods
      33             : 
      34             : /**
      35             :  * The following functions only apply when
      36             :  * AMR is enabled and thus are not present
      37             :  * otherwise.
      38             :  */
      39             : #ifdef LIBMESH_ENABLE_AMR
      40             : 
      41   321932567 : void Elem::set_p_level(unsigned int p)
      42             : {
      43             :   // Maintain the parent's p level as the minimum of it's children
      44   338375545 :   if (this->parent() != nullptr)
      45             :     {
      46    65186973 :       unsigned int parent_p_level = this->parent()->p_level();
      47             : 
      48             :       // If our new p level is less than our parents, our parents drops
      49    65186973 :       if (parent_p_level > p)
      50             :         {
      51         242 :           this->parent()->set_p_level(p);
      52             : 
      53             :           // And we should keep track of the drop, in case we need to
      54             :           // do a projection later.
      55          32 :           this->parent()->set_p_refinement_flag(Elem::JUST_COARSENED);
      56             :         }
      57             :       // If we are the lowest p level and it increases, so might
      58             :       // our parent's, but we have to check every other child to see
      59    65186731 :       else if (parent_p_level == _p_level && _p_level < p)
      60             :         {
      61       24145 :           _p_level = cast_int<unsigned char>(p);
      62       24145 :           parent_p_level = cast_int<unsigned char>(p);
      63      176941 :           for (auto & c : this->parent()->child_ref_range())
      64      152796 :             parent_p_level = std::min(parent_p_level,
      65      184838 :                                       c.p_level());
      66             : 
      67             :           // When its children all have a higher p level, the parent's
      68             :           // should rise
      69       27045 :           if (parent_p_level > this->parent()->p_level())
      70             :             {
      71        1809 :               this->parent()->set_p_level(parent_p_level);
      72             : 
      73             :               // And we should keep track of the rise, in case we need to
      74             :               // do a projection later.
      75         382 :               this->parent()->set_p_refinement_flag(Elem::JUST_REFINED);
      76             :             }
      77             : 
      78       24145 :           return;
      79             :         }
      80             :     }
      81             : 
      82    48233544 :   this->hack_p_level(p);
      83             : }
      84             : 
      85             : 
      86             : 
      87     1248720 : void Elem::refine (MeshRefinement & mesh_refinement)
      88             : {
      89       74944 :   libmesh_assert_equal_to (this->refinement_flag(), Elem::REFINE);
      90       74944 :   libmesh_assert (this->active());
      91             : 
      92     1248720 :   const unsigned int nc = this->n_children();
      93             : 
      94             :   // Create my children if necessary
      95     1248720 :   if (!_children)
      96             :     {
      97     2315626 :       _children = std::make_unique<Elem *[]>(nc);
      98             : 
      99      148730 :       unsigned int parent_p_level = this->p_level();
     100     1232178 :       const unsigned int nei = this->n_extra_integers();
     101     7766255 :       for (unsigned int c = 0; c != nc; c++)
     102             :         {
     103     6923863 :           auto current_child = Elem::build(this->type(), this);
     104     6923863 :           _children[c] = current_child.get();
     105             : 
     106      389786 :           current_child->set_refinement_flag(Elem::JUST_REFINED);
     107     6534077 :           current_child->set_p_level(parent_p_level);
     108      779572 :           current_child->set_p_refinement_flag(this->p_refinement_flag());
     109             : 
     110    53981206 :           for (auto cnode : current_child->node_index_range())
     111             :             {
     112             :               Node * node =
     113    50118409 :                 mesh_refinement.add_node(*this, c, cnode,
     114     2671280 :                                          current_child->processor_id());
     115    59735375 :               node->set_n_systems (this->n_systems());
     116    47447129 :               current_child->set_node(cnode, node);
     117             :             }
     118             : 
     119     6534077 :           Elem * added_child = mesh_refinement.add_elem (std::move(current_child));
     120     8409203 :           added_child->set_n_systems(this->n_systems());
     121      389786 :           libmesh_assert_equal_to (added_child->n_extra_integers(),
     122             :                                    this->n_extra_integers());
     123     6547919 :           for (unsigned int i=0; i != nei; ++i)
     124       12734 :             added_child->set_extra_integer(i, this->get_extra_integer(i));
     125     5754505 :         }
     126             :     }
     127             :   else
     128             :     {
     129        1156 :       unsigned int parent_p_level = this->p_level();
     130       82710 :       for (unsigned int c = 0; c != nc; c++)
     131             :         {
     132        2312 :           Elem * current_child = this->child_ptr(c);
     133       66168 :           if (current_child != remote_elem)
     134             :             {
     135        2240 :               libmesh_assert(current_child->subactive());
     136        2240 :               current_child->set_refinement_flag(Elem::JUST_REFINED);
     137       62121 :               current_child->set_p_level(parent_p_level);
     138        4480 :               current_child->set_p_refinement_flag(this->p_refinement_flag());
     139             :             }
     140             :         }
     141             :     }
     142             : 
     143             :   // Get any new remote neighbor links right; even find_neighbors
     144             :   // relies on those
     145     6040941 :   for (unsigned int s : this->side_index_range())
     146             :     {
     147     5088791 :       if (this->neighbor_ptr(s) != remote_elem)
     148     4334695 :         continue;
     149             : 
     150     1175312 :       for (unsigned int c = 0; c != nc; c++)
     151             :         {
     152        1036 :           Elem * current_child = this->child_ptr(c);
     153     2024241 :           if (current_child != remote_elem &&
     154     1010067 :               this->is_child_on_side(c, s))
     155             :             current_child->set_neighbor
     156      504077 :               (s, const_cast<RemoteElem *>(remote_elem));
     157             :         }
     158             :     }
     159             : 
     160             :   // Un-set my refinement flag now
     161       74944 :   this->set_refinement_flag(Elem::INACTIVE);
     162             : 
     163             :   // Leave the p refinement flag set - we will need that later to get
     164             :   // projection operations correct
     165             :   // this->set_p_refinement_flag(Elem::INACTIVE);
     166             : 
     167             : #ifndef NDEBUG
     168      467042 :   for (unsigned int c = 0; c != nc; c++)
     169      392098 :     if (this->child_ptr(c) != remote_elem)
     170             :       {
     171      392026 :         libmesh_assert_equal_to (this->child_ptr(c)->parent(), this);
     172      392026 :         libmesh_assert(this->child_ptr(c)->active());
     173             :       }
     174             : #endif
     175       74944 :   libmesh_assert (this->ancestor());
     176     1248720 : }
     177             : 
     178             : 
     179             : 
     180      396682 : void Elem::coarsen()
     181             : {
     182       18476 :   libmesh_assert_equal_to (this->refinement_flag(), Elem::COARSEN_INACTIVE);
     183       18476 :   libmesh_assert (!this->active());
     184             : 
     185             :   // We no longer delete children until MeshRefinement::contract()
     186             : 
     187       18476 :   unsigned int parent_p_level = 0;
     188             : 
     189      396682 :   const unsigned int n_n = this->n_nodes();
     190             : 
     191             :   // re-compute hanging node nodal locations
     192     1986142 :   for (unsigned int c = 0, nc = this->n_children(); c != nc; ++c)
     193             :     {
     194       74096 :       Elem * mychild = this->child_ptr(c);
     195     1589460 :       if (mychild == remote_elem)
     196       29746 :         continue;
     197     8943873 :       for (auto cnode : mychild->node_index_range())
     198             :         {
     199      420936 :           Point new_pos;
     200      420936 :           bool calculated_new_pos = false;
     201             : 
     202    51395254 :           for (unsigned int n=0; n<n_n; n++)
     203             :             {
     204             :               // The value from the embedding matrix
     205    44011023 :               const Real em_val = this->embedding_matrix(c,cnode,n);
     206             : 
     207             :               // The node location is somewhere between existing vertices
     208    44011023 :               if ((em_val != 0.) && (em_val != 1.))
     209             :                 {
     210    14597961 :                   new_pos.add_scaled (this->point(n), em_val);
     211      894600 :                   calculated_new_pos = true;
     212             :                 }
     213             :             }
     214             : 
     215     7384231 :           if (calculated_new_pos)
     216             :             {
     217             :               //Move the existing node back into it's original location
     218    19038800 :               for (unsigned int i=0; i<LIBMESH_DIM; i++)
     219             :                 {
     220     1571904 :                   Point & child_node = mychild->point(cnode);
     221    14279100 :                   child_node(i)=new_pos(i);
     222             :                 }
     223             :             }
     224             :         }
     225             :     }
     226             : 
     227     1986142 :   for (auto & mychild : this->child_ref_range())
     228             :     {
     229     1589460 :       if (&mychild == remote_elem)
     230       29746 :         continue;
     231       74024 :       libmesh_assert_equal_to (mychild.refinement_flag(), Elem::COARSEN);
     232       74024 :       mychild.set_refinement_flag(Elem::INACTIVE);
     233     1633666 :       if (mychild.p_level() > parent_p_level)
     234           0 :         parent_p_level = mychild.p_level();
     235             :     }
     236             : 
     237       18476 :   this->set_refinement_flag(Elem::JUST_COARSENED);
     238      396682 :   this->set_p_level(parent_p_level);
     239             : 
     240       18476 :   libmesh_assert (this->active());
     241      396682 : }
     242             : 
     243             : 
     244             : 
     245     6776970 : void Elem::contract()
     246             : {
     247             :   // Subactive elements get deleted entirely, not contracted
     248      359394 :   libmesh_assert (this->active());
     249             : 
     250             :   // Active contracted elements no longer can have children
     251      359394 :   _children.reset(nullptr);
     252             : 
     253     6776970 :   if (this->refinement_flag() == Elem::JUST_COARSENED)
     254       17896 :     this->set_refinement_flag(Elem::DO_NOTHING);
     255     6776970 : }
     256             : 
     257             : #endif // #ifdef LIBMESH_ENABLE_AMR
     258             : 
     259             : 
     260             : } // namespace libMesh

Generated by: LCOV version 1.14