libMesh
Loading...
Searching...
No Matches
elem_refinement.C
Go to the documentation of this file.
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
27namespace libMesh
28{
29
30
31//--------------------------------------------------------------------
32// Elem methods
33
39#ifdef LIBMESH_ENABLE_AMR
40
41void Elem::set_p_level(unsigned int p)
42{
43 // Maintain the parent's p level as the minimum of it's children
44 if (this->parent() != nullptr)
45 {
46 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 if (parent_p_level > p)
50 {
51 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.
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 else if (parent_p_level == _p_level && _p_level < p)
60 {
61 _p_level = cast_int<unsigned char>(p);
62 parent_p_level = cast_int<unsigned char>(p);
63 for (auto & c : this->parent()->child_ref_range())
64 parent_p_level = std::min(parent_p_level,
65 c.p_level());
66
67 // When its children all have a higher p level, the parent's
68 // should rise
69 if (parent_p_level > this->parent()->p_level())
70 {
71 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.
76 }
77
78 return;
79 }
80 }
81
82 this->hack_p_level(p);
83}
84
85
86
87void Elem::refine (MeshRefinement & mesh_refinement)
88{
89 libmesh_assert_equal_to (this->refinement_flag(), Elem::REFINE);
90 libmesh_assert (this->active());
91
92 const unsigned int nc = this->n_children();
93
94 // Create my children if necessary
95 if (!_children)
96 {
97 _children = std::make_unique<Elem *[]>(nc);
98
99 unsigned int parent_p_level = this->p_level();
100 const unsigned int nei = this->n_extra_integers();
101 for (unsigned int c = 0; c != nc; c++)
102 {
103 auto current_child = Elem::build(this->type(), this);
104 _children[c] = current_child.get();
105
106 current_child->set_refinement_flag(Elem::JUST_REFINED);
107 current_child->set_p_level(parent_p_level);
108 current_child->set_p_refinement_flag(this->p_refinement_flag());
109
110 for (auto cnode : current_child->node_index_range())
111 {
112 Node * node =
113 mesh_refinement.add_node(*this, c, cnode,
114 current_child->processor_id());
115 node->set_n_systems (this->n_systems());
116 current_child->set_node(cnode, node);
117 }
118
119 Elem * added_child = mesh_refinement.add_elem (std::move(current_child));
120 added_child->set_n_systems(this->n_systems());
121 libmesh_assert_equal_to (added_child->n_extra_integers(),
122 this->n_extra_integers());
123 for (unsigned int i=0; i != nei; ++i)
124 added_child->set_extra_integer(i, this->get_extra_integer(i));
125 }
126 }
127 else
128 {
129 unsigned int parent_p_level = this->p_level();
130 for (unsigned int c = 0; c != nc; c++)
131 {
132 Elem * current_child = this->child_ptr(c);
133 if (current_child != remote_elem)
134 {
135 libmesh_assert(current_child->subactive());
137 current_child->set_p_level(parent_p_level);
138 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 for (unsigned int s : this->side_index_range())
146 {
147 if (this->neighbor_ptr(s) != remote_elem)
148 continue;
149
150 for (unsigned int c = 0; c != nc; c++)
151 {
152 Elem * current_child = this->child_ptr(c);
153 if (current_child != remote_elem &&
154 this->is_child_on_side(c, s))
155 current_child->set_neighbor
156 (s, const_cast<RemoteElem *>(remote_elem));
157 }
158 }
159
160 // Un-set my refinement flag now
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 for (unsigned int c = 0; c != nc; c++)
169 if (this->child_ptr(c) != remote_elem)
170 {
171 libmesh_assert_equal_to (this->child_ptr(c)->parent(), this);
172 libmesh_assert(this->child_ptr(c)->active());
173 }
174#endif
175 libmesh_assert (this->ancestor());
176}
177
178
179
181{
182 libmesh_assert_equal_to (this->refinement_flag(), Elem::COARSEN_INACTIVE);
183 libmesh_assert (!this->active());
184
185 // We no longer delete children until MeshRefinement::contract()
186
187 unsigned int parent_p_level = 0;
188
189 const unsigned int n_n = this->n_nodes();
190
191 // re-compute hanging node nodal locations
192 for (unsigned int c = 0, nc = this->n_children(); c != nc; ++c)
193 {
194 Elem * mychild = this->child_ptr(c);
195 if (mychild == remote_elem)
196 continue;
197 for (auto cnode : mychild->node_index_range())
198 {
199 Point new_pos;
200 bool calculated_new_pos = false;
201
202 for (unsigned int n=0; n<n_n; n++)
203 {
204 // The value from the embedding matrix
205 const Real em_val = this->embedding_matrix(c,cnode,n);
206
207 // The node location is somewhere between existing vertices
208 if ((em_val != 0.) && (em_val != 1.))
209 {
210 new_pos.add_scaled (this->point(n), em_val);
211 calculated_new_pos = true;
212 }
213 }
214
215 if (calculated_new_pos)
216 {
217 //Move the existing node back into it's original location
218 for (unsigned int i=0; i<LIBMESH_DIM; i++)
219 {
220 Point & child_node = mychild->point(cnode);
221 child_node(i)=new_pos(i);
222 }
223 }
224 }
225 }
226
227 for (auto & mychild : this->child_ref_range())
228 {
229 if (&mychild == remote_elem)
230 continue;
231 libmesh_assert_equal_to (mychild.refinement_flag(), Elem::COARSEN);
232 mychild.set_refinement_flag(Elem::INACTIVE);
233 if (mychild.p_level() > parent_p_level)
234 parent_p_level = mychild.p_level();
235 }
236
238 this->set_p_level(parent_p_level);
239
240 libmesh_assert (this->active());
241}
242
243
244
246{
247 // Subactive elements get deleted entirely, not contracted
248 libmesh_assert (this->active());
249
250 // Active contracted elements no longer can have children
251 _children.reset(nullptr);
252
255}
256
257#endif // #ifdef LIBMESH_ENABLE_AMR
258
259
260} // namespace libMesh
unsigned int n_systems() const
Definition dof_object.h:913
unsigned int n_extra_integers() const
Returns how many extra integers are associated to the DofObject.
void set_extra_integer(const unsigned int index, const dof_id_type value)
Sets the value on this object of the extra integer associated with index, which should have been obta...
void set_n_systems(const unsigned int s)
Sets the number of systems for this DofObject.
Definition dof_object.C:142
This is the base class from which all geometric element types are derived.
Definition elem.h:96
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
Definition elem.h:3251
virtual void refine(MeshRefinement &mesh_refinement)
Refine the element.
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
void contract()
Contract an active element, i.e.
RefinementState refinement_flag() const
Definition elem.h:3227
bool active() const
Definition elem.h:2958
const Point & point(const unsigned int i) const
Definition elem.h:2462
virtual unsigned int n_nodes() const =0
const Elem * parent() const
Definition elem.h:3047
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
Definition elem.h:2635
void hack_p_level(const unsigned int p)
Sets the value of the p-refinement level for the element without altering the p-level of its ancestor...
Definition elem.h:3281
const Elem * child_ptr(unsigned int i) const
Definition elem.h:3180
bool ancestor() const
Definition elem.C:2019
@ COARSEN_INACTIVE
Definition elem.h:1452
@ JUST_COARSENED
Definition elem.h:1450
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
std::unique_ptr< Elem *[]> _children
unique_ptr to array of this element's children.
Definition elem.h:2270
virtual Real embedding_matrix(const unsigned int child_num, const unsigned int child_node_num, const unsigned int parent_node_num) const =0
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
Definition elem.h:2355
unsigned char _p_level
p refinement level - the difference between the polynomial degree on this element and the minimum pol...
Definition elem.h:2299
void coarsen()
Coarsen the element.
virtual unsigned int n_children() const =0
virtual ElemType type() const =0
IntRange< unsigned short > node_index_range() const
Definition elem.h:2700
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition elem.h:3235
bool subactive() const
Definition elem.h:2976
unsigned int p_level() const
Definition elem.h:3125
RefinementState p_refinement_flag() const
Definition elem.h:3243
void set_p_level(const unsigned int p)
Sets the value of the p-refinement level for the element.
const Elem * neighbor_ptr(unsigned int i) const
Definition elem.h:2615
IntRange< unsigned short > side_index_range() const
Definition elem.h:2727
Implements (adaptive) mesh refinement algorithms for a MeshBase.
Elem * add_elem(Elem *elem)
Adds the element elem to the mesh.
Node * add_node(Elem &parent, unsigned int child, unsigned int node, processor_id_type proc_id)
Add a node to the mesh.
A Node is like a Point, but with more information.
Definition node.h:55
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
In parallel meshes where a ghost element has neighbors which do not exist on the local processor,...
Definition remote_elem.h:61
void add_scaled(const TypeVector< T2 > &, const T &)
Add a scaled value to this vector without creating a temporary.
The libMesh namespace provides an interface to certain functionality in the library.
libmesh_assert(ctx)
const RemoteElem * remote_elem
Definition remote_elem.C:57
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real