tree.template.cc
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 // Config header generated by autoconfig
31 #ifdef HAVE_CONFIG_H
32  #include <oomph-lib-config.h>
33 #endif
34 
35 //oomph-lib headers
36 #include "tree.h"
37 
38 #include <stdio.h>
39 
40 
41 #ifndef OOMPH_TREE_TEMPLATE_CC
42 #define OOMPH_TREE_TEMPLATE_CC
43 
44 namespace oomph
45 {
46 
47 
48 //================================================================
49 /// If required, split the leaf element and create its sons
50 ///
51 /// Split is performed if
52 ///
53 /// object_pt()->to_be_refined()
54 ///
55 /// returns true.
56 ///
57 /// If this is the case, then we execute
58 ///
59 /// object_pt()->split(new_elements_pt)
60 ///
61 /// to create the sons. Pointers to the son objects are then inserted
62 /// into the son pointers of the present element. This turns the
63 /// present element into a "grey" (=non-leaf) node.
64 ///
65 //=================================================================
66 template<class ELEMENT>
68 {
69 
70 
71 #ifdef PARANOID
72  if (Son_pt.size()!=0)
73  {
74  std::string error_message =
75  "Can't split non-leaf elements (or at least I can't see\n";
76  error_message +=
77  "why you would want me to... If you're sure, then hack me... \n";
78 
79  throw OomphLibError(error_message,
80  OOMPH_CURRENT_FUNCTION,
81  OOMPH_EXCEPTION_LOCATION);
82  }
83 
84  if (Object_pt==0)
85  {
86  std::stringstream error_message;
87  error_message << "No object defined in split_if_required. Father nodes:\n";
88 
90  unsigned nnod=el_pt->nnode();
91  for (unsigned j=0;j<nnod;j++)
92  {
93  Node* nod_pt=el_pt->node_pt(j);
94  unsigned n=nod_pt->ndim();
95  for (unsigned i=0;i<n;i++)
96  {
97  error_message << nod_pt->x(i) << " ";
98  }
99  error_message << "\n";
100  }
101  throw OomphLibError(error_message.str(),
102  OOMPH_CURRENT_FUNCTION,
103  OOMPH_EXCEPTION_LOCATION);
104  }
105 
106 #endif
107 
108  // Check if refinement is required
109  if (Object_pt->to_be_refined())
110  {
111  // Perform the split for the element in question and return Vector
112  // of pointers to the newly created elements
113  Vector<ELEMENT*> new_elements_pt;
114  Object_pt->split(new_elements_pt);
115 
116  //Find the number of sons constructed by the element
117  unsigned n_sons = new_elements_pt.size();
118 
119  // Turn the new elements into QuadTrees and assign
120  // the pointers to the present element's sons
121  Son_pt.resize(n_sons);
122  Tree* father_pt = this;
123  for(unsigned i_son=0;i_son<n_sons;i_son++)
124  {
125  Son_pt[i_son]= construct_son(new_elements_pt[i_son],
126  father_pt,i_son);
127  // Now that the son knows its position in the tree, we can set it
128  // up as a proper element (e.g. p-refineable stuff)
129  Son_pt[i_son]->object_pt()->initial_setup();
130  }
131  }
132 }
133 
134 
135 //================================================================
136 /// If required, p-refine/unrefine the leaf element
137 ///
138 /// p-refinement is performed if
139 ///
140 /// object_pt()->to_be_p_refined()
141 ///
142 /// returns true. p-unrefinement is performed if
143 ///
144 /// object_pt()->to_be_p_unrefined()
145 ///
146 /// returns true.
147 ///
148 /// If this is the case, then we execute
149 ///
150 /// object_pt()->p_refine(+/-1,mesh_pt,clone_pt)
151 ///
152 /// to p-refine the element, where mesh_pt is a pointer to the
153 /// mesh that the element lives in, and clone_pt is a pointer to
154 /// a GeneralisedElement that has all the information that would
155 /// be needed from the father element during h-refinement.
156 ///
157 //=================================================================
158 template<class ELEMENT>
160 {
161 
162 
163 #ifdef PARANOID
164  if (Son_pt.size()!=0)
165  {
166  std::string error_message =
167  "Can't p-refine non-leaf elements (or at least I can't see\n";
168  error_message +=
169  "why you would want me to... If you're sure, then hack me... \n";
170 
171  throw OomphLibError(error_message,
172  OOMPH_CURRENT_FUNCTION,
173  OOMPH_EXCEPTION_LOCATION);
174  }
175 
176  if (Object_pt==0)
177  {
178  std::stringstream error_message;
179  error_message << "No object defined in p_refine_if_required. Father nodes:\n";
180 
182  unsigned nnod=el_pt->nnode();
183  for (unsigned j=0;j<nnod;j++)
184  {
185  Node* nod_pt=el_pt->node_pt(j);
186  unsigned n=nod_pt->ndim();
187  for (unsigned i=0;i<n;i++)
188  {
189  error_message << nod_pt->x(i) << " ";
190  }
191  error_message << "\n";
192  }
193  throw OomphLibError(error_message.str(),
194  OOMPH_CURRENT_FUNCTION,
195  OOMPH_EXCEPTION_LOCATION);
196  }
197 
198 #endif
199 
200  //Cast to p-refineable element
201  PRefineableElement* p_ref_obj_pt
202  = dynamic_cast<PRefineableElement*>(Object_pt);
203 
204  //Check if we can p-refine the element
205  if (p_ref_obj_pt==0)
206  {
207  throw OomphLibError("Element cannot be p-refined",
208  OOMPH_CURRENT_FUNCTION,
209  OOMPH_EXCEPTION_LOCATION);
210  }
211 
212 
213  // Create a temporary clone of the element to be refined.
214  // This is required so that the element can read data from "itself"
215  // while it rebuilds itself with a new p-order. Only the information
216  // required for the p-refinement is copied across.
217 
218  // Make new element (using ELEMENT's standard constructor)
219  ELEMENT* clone_pt = new ELEMENT();
220 
221  // Do initial setup with myself as the clone's adopted father
222  clone_pt->initial_setup(this);
223 
224  // All that is left to do is to "build" the clone. It has the same
225  // nodes as me, so we can just copy across their pointers
226  for(unsigned j=0; j<clone_pt->nnode(); j++)
227  {
228  clone_pt->node_pt(j) = p_ref_obj_pt->node_pt(j);
229  }
230 
231 
232  // Check if refinement is required
233  if (p_ref_obj_pt->to_be_p_refined())
234  {
235  // Perform the split for the element in question and return Vector
236  // of pointers to the newly created elements
237  p_ref_obj_pt->p_refine(1,mesh_pt,clone_pt);
238  }
239  // Check if unrefinement is required
240  else if (p_ref_obj_pt->to_be_p_unrefined())
241  {
242  // Perform the split for the element in question and return Vector
243  // of pointers to the newly created elements
244  p_ref_obj_pt->p_refine(-1,mesh_pt,clone_pt);
245  }
246 
247 
248  //Delete the temporary copy of the element
249  delete clone_pt;
250 
251 }
252 
253 
254 }
255 
256 #endif
Vector< Tree * > Son_pt
Vector of pointers to the sons of the Tree.
Definition: tree.h:278
RefineableElement * Object_pt
Pointer to the object represented by the tree.
Definition: tree.h:287
bool to_be_p_unrefined()
Has the element been selected for p-unrefinement?
RefineableElement * object_pt() const
Return the pointer to the object (RefineableElement) represented by the tree.
Definition: tree.h:102
void split(Vector< ELEMENT * > &son_pt) const
Split the element into the number of sons to be constructed and return a vector of pointers to the so...
virtual Tree * construct_son(RefineableElement *const &object_pt, Tree *const &father_pt, const int &son_type)=0
A function that constructs a specific type of tree. This MUST be overloaded for each specific tree ty...
cstr elem_len * i
Definition: cfortran.h:607
bool to_be_p_refined()
Has the element been selected for refinement?
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:995
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2097
virtual void p_refine(const int &inc, Mesh *const &mesh_pt, GeneralisedElement *const &clone_pt)=0
p-refine the element
Tree * Father_pt
Pointer to the Father of the Tree.
Definition: tree.h:275
bool to_be_refined()
Has the element been selected for refinement?
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
p-refineable version of RefineableElement
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2134
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:992
void p_refine_if_required(Mesh *&mesh_pt)
If required, p-refine the leaf – criterion: bool object_pt()-> to_be_p_refined() = true or bool objec...
Tree * father_pt() const
Return pointer to father: NULL if it's a root node.
Definition: tree.h:221
void split_if_required()
If required, split the leaf and create its sons – criterion: bool object_pt()-> to_be_refined() = tru...
A general mesh class.
Definition: mesh.h:74