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