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-2022 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
40namespace 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
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
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2210
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
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
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
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
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...
RefineableElement * object_pt() const
Return the pointer to the object (RefineableElement) represented by the tree.
Definition: tree.h:88
void split_if_required()
If required, split the leaf and create its sons – criterion: bool object_pt()-> to_be_refined() = tru...
Tree * father_pt() const
Return pointer to father: NULL if it's a root node.
Definition: tree.h:235
Vector< Tree * > Son_pt
Vector of pointers to the sons of the Tree.
Definition: tree.h:299
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...
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.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...