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