refineable_quad_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: 1182 $
7 //LIC//
8 //LIC// $LastChangedDate: 2016-05-20 16:50:20 +0100 (Fri, 20 May 2016) $
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 QMESH2OOMPH_D_HEADER
31 #define QMESH2OOMPH_D_HEADER
32 
33 #include<limits.h>
34 
35 #include "quad_mesh.h"
36 #include "refineable_mesh.h"
38 //Include to fill in additional_setup_shared_node_scheme() function
40 
41 namespace oomph
42 {
43 
44 //=======================================================================
45 /// Intermediate mesh class that implements the mesh adaptation functions
46 /// specified in the TreeBasedRefineableMesh class for meshes that contain the
47 /// refineable variant of QElement s [The class ELEMENT provided
48 /// as the template parameter must be of type
49 /// RefineableQElement<2>].
50 ///
51 /// Mesh adaptation/refinement is implemented by QuadTree
52 /// procedures and any concrete implementation of this class needs to
53 /// provide a QuadTreeForest representation of the initial (coarse) mesh.
54 //=======================================================================
55 template <class ELEMENT>
56 class RefineableQuadMesh : public virtual TreeBasedRefineableMesh<ELEMENT>,
57 public virtual QuadMeshBase
58 {
59 
60 public:
61 
62  /// Constructor: Setup static quadtree data
64  {
65  // QuadTree static data needs to be setup before quadtree-based mesh
66  // refinement works
68  }
69 
70  /// Broken copy constructor
72  {
73  BrokenCopy::broken_copy("RefineableQuadMesh");
74  }
75 
76  /// Broken assignment operator
77 //Commented out broken assignment operator because this can lead to a conflict warning
78 //when used in the virtual inheritence hierarchy. Essentially the compiler doesn't
79 //realise that two separate implementations of the broken function are the same and so,
80 //quite rightly, it shouts.
81  /*void operator=(const RefineableQuadMesh&)
82  {
83  BrokenCopy::broken_assign("RefineableQuadMesh");
84  }*/
85 
86  /// Destructor:
87  virtual ~RefineableQuadMesh() {}
88 
89 
90  /// \short Set up the tree forest associated with the Mesh.
91  /// Forwards call to setup_quadtree_forest()
92  virtual void setup_tree_forest()
93  {
95  }
96 
97  /// \short Set up QuadTreeForest. Wipes any existing tree structure below
98  /// the minimum refinement level and regards the elements at that level
99  /// as the root trees in the forest.
101  {
102  // A forst pointer is setup at least once when the mesh is initially
103  // created in serial and stays around
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 #ifdef OOMPH_HAS_MPI
116 
117  // Reconcile between processors: If (e.g. following distribution/pruning)
118  // the mesh has no elements on this processor) then ignore its
119  // contribution to the poll of max/min refinement levels
120  int int_local_min_ref=local_min_ref;
121 
122  if (this->nelement()==0)
123  {
124  int_local_min_ref=INT_MAX;
125  }
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 
132  unsigned min_ref=unsigned(int_min_ref);
133 
134 #else
135 
136  unsigned min_ref=local_min_ref;
137 
138 #endif
139 
140  // If we have no elements there's nothing more to be done --
141  // we only came in here to participate in the communication
142  if (this->nelement()==0)
143  {
144  // Flush the Forest's current trees
145  this->Forest_pt->flush_trees();
146 
147  // Delete the old Forest
148  delete this->Forest_pt;
149 
150  // Empty dummy vector to build empty forest
151  Vector<TreeRoot*> trees_pt;
152 
153  // Make a new (empty) Forest
154  this->Forest_pt = new QuadTreeForest(trees_pt);
155  return;
156  }
157 
158  // Vector to store trees for new Forest
159  Vector<TreeRoot*> trees_pt;
160 
161  // Loop over tree nodes (e.g. elements)
162  unsigned n_tree_nodes=all_tree_nodes_pt.size();
163  for (unsigned e=0;e<n_tree_nodes;e++)
164  {
165  Tree* tree_pt=all_tree_nodes_pt[e];
166 
167  // If the object_pt has been flushed then we don't want to keep
168  // this tree
169  if (tree_pt->object_pt()!=0)
170  {
171  // Get the refinement level of the current tree node
172  RefineableElement* el_pt=dynamic_cast<RefineableElement*>
173  (tree_pt->object_pt());
174  unsigned level=el_pt->refinement_level();
175 
176  // If we are below the minimum refinement level, remove tree
177  if (level<min_ref)
178  {
179  // Flush sons for this tree
180  tree_pt->flush_sons();
181 
182  // Delete the tree (no recursion)
183  delete tree_pt;
184 
185  // Delete the element
186  delete el_pt;
187  }
188  else if (level==min_ref)
189  {
190  // Get the sons (if there are any) and store them
191  unsigned n_sons=tree_pt->nsons();
192  Vector<Tree*> backed_up_sons(n_sons);
193  for (unsigned i_son=0;i_son<n_sons;i_son++)
194  {
195  backed_up_sons[i_son]=tree_pt->son_pt(i_son);
196  }
197 
198  // Make the element into a new tree-root
199  QuadTreeRoot* tree_root_pt=new QuadTreeRoot(el_pt);
200 
201  // Pass sons
202  tree_root_pt->set_son_pt(backed_up_sons);
203 
204  // Loop over sons and make the new treeroot their father
205  for (unsigned i_son=0;i_son<n_sons;i_son++)
206  {
207  Tree* son_pt=backed_up_sons[i_son];
208 
209  // Tell the son about its new father (which is also the root)
210  son_pt->set_father_pt(tree_root_pt);
211  son_pt->root_pt()=tree_root_pt;
212 
213  // ...and then tell all the descendants too
214  Vector<Tree*> all_sons_pt;
215  son_pt->stick_all_tree_nodes_into_vector(all_sons_pt);
216  unsigned n=all_sons_pt.size();
217  for (unsigned i=0;i<n;i++)
218  {
219  all_sons_pt[i]->root_pt()=tree_root_pt;
220  }
221  }
222 
223  // Add tree-root to the trees_pt vector
224  trees_pt.push_back(tree_root_pt);
225 
226  // Now kill the original (non-root) tree: First
227  // flush sons for this tree
228  tree_pt->flush_sons();
229 
230  // ...then delete the tree (no recursion)
231  delete tree_pt;
232  }
233  }
234  else // tree_pt->object_pt() is null, so delete tree
235  {
236  // Flush sons for this tree
237  tree_pt->flush_sons();
238 
239  // Delete the tree (no recursion)
240  delete tree_pt;
241  }
242  }
243 
244  // Flush the Forest's current trees
245  this->Forest_pt->flush_trees();
246 
247  // Delete the old Forest
248  delete this->Forest_pt;
249 
250  // Make a new Forest with the trees_pt roots created earlier
251  this->Forest_pt = new QuadTreeForest(trees_pt);
252 
253  }
254  else // Create a new Forest from scratch in the "usual" uniform way
255  {
256  // Each finite element in the coarse base mesh gets associated
257  // with (the root of) a QuadTree. Store QuadTreeRoots in vector:
258  Vector<TreeRoot*> trees_pt;
259 
260  // Loop over all elements, build corresponding QuadTree
261  // and store QuadTreeRoots in vector:
262  unsigned n_element=this->nelement();
263  for (unsigned e=0;e<n_element;e++)
264  {
265  // Get pointer to full element type
266  ELEMENT* el_pt=dynamic_cast<ELEMENT*>(this->element_pt(e));
267 
268  // Build associated quadtree(root) -- pass pointer to corresponding
269  // finite element and add the pointer to vector of quadtree (roots):
270  trees_pt.push_back(new QuadTreeRoot(el_pt));
271  }
272 
273  // Plant QuadTreeRoots in QuadTreeForest
274  this->Forest_pt = new QuadTreeForest(trees_pt);
275  }
276  }
277 
278 };
279 
280 }
281 
282 #endif
virtual ~RefineableQuadMesh()
Broken assignment operator.
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
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
void flush_sons()
Flush the sons.
Definition: tree.h:137
cstr elem_len * i
Definition: cfortran.h:607
void setup_quadtree_forest()
Set up QuadTreeForest. Wipes any existing tree structure below the minimum refinement level and regar...
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.
RefineableQuadMesh()
Constructor: Setup static quadtree data.
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:587
static void setup_static_data()
Setup the static data, rotation and reflection schemes, etc.
Definition: quadtree.cc:126
void set_father_pt(Tree *const &father_pt)
Set the father.
Definition: tree.h:224
unsigned refinement_level() const
Return the Refinement level.
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
Definition: mesh.h:470
RefineableQuadMesh(const RefineableQuadMesh &dummy)
Broken copy constructor.
Base class for quad meshes (meshes made of 2D quad elements).
Definition: quad_mesh.h:61
void stick_all_tree_nodes_into_vector(Vector< Tree * > &)
Traverse and stick pointers to all "nodes" into Vector.
Definition: tree.cc:276
virtual void setup_tree_forest()
Set up the tree forest associated with the Mesh. Forwards call to setup_quadtree_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