refineable_brick_mesh.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 #ifndef QMESH3OOMPH_D_HEADER
27 #define QMESH3OOMPH_D_HEADER
28 
29 
30 // Config header generated by autoconfig
31 #ifdef HAVE_CONFIG_H
32 #include <oomph-lib-config.h>
33 #endif
34 
35 #include <limits.h>
36 
37 
38 // ooomph-lib includes
39 #include "brick_mesh.h"
40 #include "refineable_mesh.h"
42 // Include to fill in additional_setup_shared_node_scheme() function
44 
45 namespace oomph
46 {
47  //=======================================================================
48  /// Intermediate mesh class that implements the mesh adaptation functions
49  /// specified in the TreeBasedRefineableMesh class for meshes that contain the
50  /// refineable variant of QElement s [The class ELEMENT provided
51  /// as the template parameter must be of type
52  /// RefineableQElement<3>].
53  ///
54  /// Mesh adaptation/refinement is implemented by OcTree
55  /// procedures and any concrete implementation of this class needs to
56  /// provide a OcTreeForest representation of the initial (coarse) mesh.
57  //=======================================================================
58  template<class ELEMENT>
60  public virtual BrickMeshBase
61  {
62  public:
63  /// Constructor: Setup static octree data
65  {
66  // OcTree static data needs to be setup before octree-based mesh
67  // refinement works
69  }
70 
71  /// Broken copy constructor
72  RefineableBrickMesh(const RefineableBrickMesh& dummy) = delete;
73 
74  /// Broken assignment operator
75  void operator=(const RefineableBrickMesh&) = delete;
76 
77  /// Destructor:
78  virtual ~RefineableBrickMesh() {}
79 
80  /// Set up the tree forest associated with the Mesh.
81  /// Forwards call to setup_octree_forest()
82  virtual void setup_tree_forest()
83  {
85  }
86 
87  /// Do what it says...
89  {
90  if (this->Forest_pt != 0)
91  {
92  // Get all the tree nodes
93  Vector<Tree*> all_tree_nodes_pt;
94  this->Forest_pt->stick_all_tree_nodes_into_vector(all_tree_nodes_pt);
95 
96  // Get min and max refinement level from the tree
97  unsigned local_min_ref = 0;
98  unsigned local_max_ref = 0;
99  this->get_refinement_levels(local_min_ref, local_max_ref);
100 
101  unsigned min_ref = local_min_ref;
102 #ifdef OOMPH_HAS_MPI
103  if (Comm_pt != 0)
104  {
105  // Reconcile between processors: If (e.g. following
106  // distribution/pruning) the mesh has no elements on this processor)
107  // then ignore its contribution to the poll of max/min refinement
108  // levels
109  int int_local_min_ref = local_min_ref;
110  if (this->nelement() == 0)
111  {
112  int_local_min_ref = INT_MAX;
113  }
114  int int_min_ref = 0;
115  MPI_Allreduce(&int_local_min_ref,
116  &int_min_ref,
117  1,
118  MPI_INT,
119  MPI_MIN,
120  Comm_pt->mpi_comm());
121  min_ref = int_min_ref;
122  }
123 #endif
124 
125  // If we have no elements there's nothing more to be done --
126  // we only came in here to participate in the communication
127  if (this->nelement() == 0)
128  {
129  // Flush the Forest's current trees
130  this->Forest_pt->flush_trees();
131 
132  // Delete the old Forest
133  delete this->Forest_pt;
134 
135  // Empty dummy vector to build empty forest
136  Vector<TreeRoot*> trees_pt;
137 
138  // Make a new (empty) Forest
139  this->Forest_pt = new OcTreeForest(trees_pt);
140 
141  return;
142  }
143 
144 
145  // Vector to store trees for new Forest
146  Vector<TreeRoot*> trees_pt;
147 
148  // Loop over tree nodes (e.g. elements)
149  unsigned n_tree_nodes = all_tree_nodes_pt.size();
150  for (unsigned e = 0; e < n_tree_nodes; e++)
151  {
152  Tree* tree_pt = all_tree_nodes_pt[e];
153 
154  // If the object_pt has been flushed then we don't want to keep
155  // this tree
156  if (tree_pt->object_pt() != 0)
157  {
158  // Get the refinement level of the current tree node
159  RefineableElement* el_pt =
160  dynamic_cast<RefineableElement*>(tree_pt->object_pt());
161  unsigned level = el_pt->refinement_level();
162 
163  // If we are below the minimum refinement level, remove tree
164  if (level < min_ref)
165  {
166  // Flush sons for this tree
167  tree_pt->flush_sons();
168 
169  // Delete the tree (no recursion)
170  delete tree_pt;
171 
172  // Delete the element
173  delete el_pt;
174  }
175  else if (level == min_ref)
176  {
177  // Get the sons (if there are any) and store them
178  unsigned n_sons = tree_pt->nsons();
179  Vector<Tree*> backed_up_sons(n_sons);
180  for (unsigned i_son = 0; i_son < n_sons; i_son++)
181  {
182  backed_up_sons[i_son] = tree_pt->son_pt(i_son);
183  }
184 
185  // Make the element into a new treeroot
186  OcTreeRoot* tree_root_pt = new OcTreeRoot(el_pt);
187 
188 
189  // Pass sons
190  tree_root_pt->set_son_pt(backed_up_sons);
191 
192  // Loop over sons and make the new treeroot their father
193  for (unsigned i_son = 0; i_son < n_sons; i_son++)
194  {
195  Tree* son_pt = backed_up_sons[i_son];
196 
197  // Tell the son about its new father (which is also the root)
198  son_pt->set_father_pt(tree_root_pt);
199  son_pt->root_pt() = tree_root_pt;
200 
201  // ...and then tell all the descendants too
202  Vector<Tree*> all_sons_pt;
203  son_pt->stick_all_tree_nodes_into_vector(all_sons_pt);
204  unsigned n = all_sons_pt.size();
205  for (unsigned i = 0; i < n; i++)
206  {
207  all_sons_pt[i]->root_pt() = tree_root_pt;
208  }
209  }
210 
211  // Add tree root to the trees_pt vector
212  trees_pt.push_back(tree_root_pt);
213 
214  // Now kill the original (non-root) tree: First
215  // flush sons for this tree
216  tree_pt->flush_sons();
217 
218  // ...then delete the tree (no recursion)
219  delete tree_pt;
220  }
221  }
222  else // tree_pt->object_pt() is null, so delete tree
223  {
224  // Flush sons for this tree
225  tree_pt->flush_sons();
226 
227  // Delete the tree (no recursion)
228  delete tree_pt;
229  }
230  }
231 
232  // Flush the Forest's current trees
233  this->Forest_pt->flush_trees();
234 
235  // Delete the old Forest
236  delete this->Forest_pt;
237 
238  // Make a new Forest with the trees_pt roots created earlier
239  this->Forest_pt = new OcTreeForest(trees_pt);
240  }
241  else // Create a new Forest from scratch in the "usual" uniform way
242  {
243  // Turn elements into individual octrees and plant in forest
244  Vector<TreeRoot*> trees_pt;
245  unsigned nel = nelement();
246  for (unsigned iel = 0; iel < nel; iel++)
247  {
248  // Get pointer to full element type
249  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(element_pt(iel));
250 
251  // Build associated octree(root) -- pass pointer to corresponding
252  // finite element and add the pointer to vector of octree (roots):
253  OcTreeRoot* octree_root_pt = new OcTreeRoot(el_pt);
254  trees_pt.push_back(octree_root_pt);
255  }
256  // Plant OcTreeRoots in OcTreeForest
257  this->Forest_pt = new OcTreeForest(trees_pt);
258  }
259  }
260 
261  protected:
262  };
263 
264 } // namespace oomph
265 
266 #endif
e
Definition: cfortran.h:571
cstr elem_len * i
Definition: cfortran.h:603
//////////////////////////////////////////////////////////////////////// ////////////////////////////...
Definition: brick_mesh.h:178
OomphCommunicator * Comm_pt
Pointer to communicator – set to NULL if mesh is not distributed.
Definition: mesh.h:119
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
Definition: mesh.h:460
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:590
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
Definition: octree.h:928
OcTreeRoot is a OcTree that forms the root of a (recursive) octree. The "root node" is special as it ...
Definition: octree.h:611
static void setup_static_data()
Setup the static data, rotation and reflection schemes, etc.
Definition: octree.cc:1040
Intermediate mesh class that implements the mesh adaptation functions specified in the TreeBasedRefin...
virtual ~RefineableBrickMesh()
Destructor:
RefineableBrickMesh(const RefineableBrickMesh &dummy)=delete
Broken copy constructor.
void setup_octree_forest()
Do what it says...
RefineableBrickMesh()
Constructor: Setup static octree data.
void operator=(const RefineableBrickMesh &)=delete
Broken assignment operator.
virtual void setup_tree_forest()
Set up the tree forest associated with the Mesh. Forwards call to setup_octree_forest()
RefineableElements are FiniteElements that may be subdivided into children to provide a better local ...
unsigned refinement_level() const
Return the Refinement level.
virtual void get_refinement_levels(unsigned &min_refinement_level, unsigned &max_refinement_level)
Get max/min refinement levels in mesh.
TreeForest * Forest_pt
Forest representation of the mesh.
///////////////////////////////////////////////////////////////// ///////////////////////////////////...
void flush_trees()
Flush trees from forest.
Definition: tree.h:472
void stick_all_tree_nodes_into_vector(Vector< Tree * > &all_forest_nodes)
Traverse forest and stick pointers to all "nodes" into Vector.
Definition: tree.cc:405
A generalised tree base class that abstracts the common functionality between the quad- and octrees u...
Definition: tree.h:74
void stick_all_tree_nodes_into_vector(Vector< Tree * > &)
Traverse and stick pointers to all "nodes" into Vector.
Definition: tree.cc:277
RefineableElement * object_pt() const
Return the pointer to the object (RefineableElement) represented by the tree.
Definition: tree.h:88
unsigned nsons() const
Return number of sons (zero if it's a leaf node)
Definition: tree.h:129
void flush_sons()
Flush the sons.
Definition: tree.h:135
Tree * son_pt(const int &son_index) const
Return pointer to the son for a given index. Note that to aid code readability specific enums have be...
Definition: tree.h:103
void set_son_pt(const Vector< Tree * > &son_pt)
Set vector of pointers to sons, indexed by the appropriate enum that identies son types....
Definition: tree.h:123
void set_father_pt(Tree *const &father_pt)
Set the father.
Definition: tree.h:241
TreeRoot *& root_pt()
Return pointer to root of the tree.
Definition: tree.h:141
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition: Vector.h:58
//////////////////////////////////////////////////////////////////// ////////////////////////////////...