oomph::BinaryTree Class Reference

#include <binary_tree.h>

+ Inheritance diagram for oomph::BinaryTree:

Public Member Functions

virtual ~BinaryTree ()
 
 BinaryTree (const BinaryTree &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const BinaryTree &)=delete
 Broken assignment operator. More...
 
Treeconstruct_son (RefineableElement *const &object_pt, Tree *const &father_pt, const int &son_type)
 
BinaryTreegteq_edge_neighbour (const int &direction, Vector< double > &s_in_neighbour, int &edge, int &diff_level, bool &in_neighbouring_tree) const
 
unsigned self_test ()
 
- Public Member Functions inherited from oomph::Tree
virtual ~Tree ()
 
 Tree (const Tree &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const Tree &)=delete
 Broken assignment operator. More...
 
RefineableElementobject_pt () const
 
void flush_object ()
 Flush the object represented by the tree. More...
 
Treeson_pt (const int &son_index) const
 
void set_son_pt (const Vector< Tree * > &son_pt)
 
unsigned nsons () const
 Return number of sons (zero if it's a leaf node) More...
 
void flush_sons ()
 Flush the sons. More...
 
TreeRoot *& root_pt ()
 Return pointer to root of the tree. More...
 
TreeRootroot_pt () const
 Return pointer to root of the tree (const version) More...
 
template<class ELEMENT >
void split_if_required ()
 
template<class ELEMENT >
void p_refine_if_required (Mesh *&mesh_pt)
 
void merge_sons_if_required (Mesh *&mesh_pt)
 
void deactivate_object ()
 Call the RefineableElement's deactivate_element() function. More...
 
void traverse_all (Tree::VoidMemberFctPt member_function)
 
void traverse_all (Tree::VoidMeshPtArgumentMemberFctPt member_function, Mesh *&mesh_pt)
 
void traverse_all_but_leaves (Tree::VoidMemberFctPt member_function)
 
void traverse_leaves (Tree::VoidMemberFctPt member_function)
 
void traverse_leaves (Tree::VoidMeshPtArgumentMemberFctPt member_function, Mesh *&mesh_pt)
 
void stick_leaves_into_vector (Vector< Tree * > &)
 Traverse tree and stick pointers to leaf "nodes" (only) into Vector. More...
 
void stick_all_tree_nodes_into_vector (Vector< Tree * > &)
 Traverse and stick pointers to all "nodes" into Vector. More...
 
int son_type () const
 Return son type. More...
 
bool is_leaf ()
 Return true if the tree is a leaf node. More...
 
Treefather_pt () const
 Return pointer to father: NULL if it's a root node. More...
 
void set_father_pt (Tree *const &father_pt)
 Set the father. More...
 
unsigned level () const
 Return the level of the Tree (root=0) More...
 

Static Public Member Functions

static void setup_static_data ()
 Set up the static data, reflection schemes, etc. More...
 
static void doc_neighbours (Vector< Tree * > forest_nodes_pt, std::ofstream &neighbours_file, std::ofstream &neighbours_txt_file, double &max_error)
 
- Static Public Member Functions inherited from oomph::Tree
static doublemax_neighbour_finding_tolerance ()
 

Static Public Attributes

static Vector< std::string > Direct_string
 Translate (enumerated) directions into strings. More...
 
- Static Public Attributes inherited from oomph::Tree
static const int OMEGA = 26
 Default value for an unassigned neighbour. More...
 

Protected Member Functions

 BinaryTree ()
 Default constructor (empty and broken) More...
 
 BinaryTree (RefineableElement *const &object_pt)
 
 BinaryTree (RefineableElement *const &object_pt, Tree *const &father_pt, const int &son_type)
 
- Protected Member Functions inherited from oomph::Tree
 Tree ()
 Default constructor (empty and broken) More...
 
 Tree (RefineableElement *const &object_pt)
 
 Tree (RefineableElement *const &object_pt, Tree *const &father_pt, const int &son_type)
 

Static Protected Attributes

static bool Static_data_has_been_setup = false
 Boolean indicating that static member data has been setup. More...
 
- Static Protected Attributes inherited from oomph::Tree
static double Max_neighbour_finding_tolerance = 1.0e-14
 

Private Member Functions

BinaryTreegteq_edge_neighbour (const int &direction, double &s_diff, int &diff_level, bool &in_neighbouring_tree, int max_level, BinaryTreeRoot *const &orig_root_pt) const
 

Static Private Attributes

static Vector< std::string > Colour
 Colours for neighbours in various directions. More...
 
static Vector< doubleS_base
 
static Vector< intReflect_edge
 Get opposite edge, e.g. Reflect_edge[L]=R. More...
 
static DenseMatrix< boolIs_adjacent
 
static DenseMatrix< intReflect
 

Additional Inherited Members

- Public Types inherited from oomph::Tree
typedef void(Tree::* VoidMemberFctPt) ()
 Function pointer to argument-free void Tree member function. More...
 
typedef void(Tree::* VoidMeshPtArgumentMemberFctPt) (Mesh *&mesh_pt)
 
- Protected Attributes inherited from oomph::Tree
TreeRootRoot_pt
 Pointer to the root of the tree. More...
 
TreeFather_pt
 Pointer to the Father of the Tree. More...
 
Vector< Tree * > Son_pt
 Vector of pointers to the sons of the Tree. More...
 
int Level
 Level of the Tree (level 0 = root) More...
 
int Son_type
 Son type (e.g. SW/SE/NW/NE in a quadtree) More...
 
RefineableElementObject_pt
 Pointer to the object represented by the tree. More...
 

Detailed Description

BinaryTree class: Recursively defined, generalised binary tree.

A BinaryTree has:

  • a pointer to the object (of type RefineableQElement<1>) that it represents in a mesh refinement context.
  • a Vector of pointers to its two (L/R) sons (which are themselves binary trees). If the Vector of pointers to the sons has zero length, the BinaryTree is a "leaf node" in the overall binary tree.
  • a pointer to its father. If this pointer is NULL, the BinaryTree is the root node of the overall binary tree. This data is stored in the Tree base class.

The tree can also be part of a forest. If that is the case, the root will have pointers to the roots of neighbouring binary trees.

The objects contained in the binary tree are assumed to be line elements whose geometry is parametrised by local coordinates \( {\bf s} \in [-1,1] \).

The tree can be traversed and actions performed at all its "nodes" or only at the leaf "nodes" ("nodes" without sons).

Finally, the leaf "nodes" can be split depending on a criteria defined by the object.

Note that BinaryTrees are only generated by splitting existing BinaryTrees. Therefore, the constructors are protected. The only BinaryTree that "Joe User" can create is the (derived) class BinaryTreeRoot.

Constructor & Destructor Documentation

◆ ~BinaryTree()

virtual oomph::BinaryTree::~BinaryTree ( )
inlinevirtual

Destructor. Note: Deleting a binary tree also deletes the objects associated with all non-leaf nodes!

96 {}

◆ BinaryTree() [1/4]

oomph::BinaryTree::BinaryTree ( const BinaryTree dummy)
delete

Broken copy constructor.

◆ BinaryTree() [2/4]

oomph::BinaryTree::BinaryTree ( )
inlineprotected

Default constructor (empty and broken)

167  {
168  throw OomphLibError(
169  "Don't call an empty constructor for a BinaryTree object",
172  }
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86

References OOMPH_CURRENT_FUNCTION, and OOMPH_EXCEPTION_LOCATION.

Referenced by construct_son().

◆ BinaryTree() [3/4]

oomph::BinaryTree::BinaryTree ( RefineableElement *const &  object_pt)
inlineprotected

Default constructor for empty (root) tree: no father, no sons; just pass a pointer to its object. Protected because BinaryTrees can only be created internally, during the split operation. Only BinaryTreeRoots can be created externally.

178 : Tree(object_pt) {}
RefineableElement * object_pt() const
Definition: tree.h:88
Tree()
Default constructor (empty and broken)
Definition: tree.h:266

◆ BinaryTree() [4/4]

oomph::BinaryTree::BinaryTree ( RefineableElement *const &  object_pt,
Tree *const &  father_pt,
const int son_type 
)
inlineprotected

Constructor for tree that has a father: Pass it the pointer to its object, the pointer to its father and tell it what type of son (L/R) it is. Protected because BinaryTrees can only be created internally, during the split operation. Only BinaryTreeRoots can be created externally.

189  {
190  }
Tree * father_pt() const
Return pointer to father: NULL if it's a root node.
Definition: tree.h:235
int son_type() const
Return son type.
Definition: tree.h:214

Member Function Documentation

◆ construct_son()

Tree* oomph::BinaryTree::construct_son ( RefineableElement *const &  object_pt,
Tree *const &  father_pt,
const int son_type 
)
inlinevirtual

Overload the function construct_son to ensure that the son is a specific BinaryTree and not a general Tree.

Implements oomph::Tree.

109  {
110  BinaryTree* temp_binary_pt =
112  return temp_binary_pt;
113  }
BinaryTree()
Default constructor (empty and broken)
Definition: binary_tree.h:166

References BinaryTree(), oomph::Tree::father_pt(), oomph::Tree::object_pt(), and oomph::Tree::son_type().

◆ doc_neighbours()

void oomph::BinaryTree::doc_neighbours ( Vector< Tree * >  forest_nodes_pt,
std::ofstream &  neighbours_file,
std::ofstream &  neighbours_txt_file,
double max_error 
)
static

Doc/check all neighbours of binary tree (nodes) contained in the Vector forest_node_pt. Output into neighbours_file which can be viewed from tecplot with BinaryTreeNeighbours.mcr. Neighbour info and errors are displayed on neighbours_txt_file. Finally, compute the maximum error between vertices when viewed from the neighbouring element. If the two filestreams are closed, output is suppressed.

Doc/check all neighbours of binary tree ("nodes") contained in the Vector forest_node_pt. Output into neighbours_file which can be viewed from tecplot with BinaryTreeNeighbours.mcr. Neighbour info and errors are displayed on neighbours_txt_file. Finally, compute the maximum error between vertices when viewed from neighbouring element. Output is suppressed if the output streams are closed.

672  {
673  using namespace BinaryTreeNames;
674 
675  int diff_level;
676  double s_diff;
677  bool in_neighbouring_tree;
678  int edge = OMEGA;
679 
680  Vector<double> s(1);
681  Vector<double> x(1);
682  Vector<int> prev_son_type;
683 
684  Vector<double> s_in_neighbour(1);
685 
686  Vector<double> x_small(1);
687  Vector<double> x_large(1);
688 
689  // Initialise error in vertex positions
690  max_error = 0.0;
691 
692  // Loop over all elements to assign numbers for plotting
693  // -----------------------------------------------------
694  unsigned long num_nodes = forest_nodes_pt.size();
695  for (unsigned long i = 0; i < num_nodes; i++)
696  {
697  // Set number
698  forest_nodes_pt[i]->object_pt()->set_number(i);
699  }
700 
701  // Loop over all elements for checks
702  // ---------------------------------
703  for (unsigned long i = 0; i < num_nodes; i++)
704  {
705  // Doc the element itself
706  BinaryTree* el_pt = dynamic_cast<BinaryTree*>(forest_nodes_pt[i]);
707 
708  // If the object is incomplete, complain
709  if (el_pt->object_pt()->nodes_built())
710  {
711  // Print it
712  if (neighbours_file.is_open())
713  {
714  dynamic_cast<RefineableQElement<1>*>(el_pt->object_pt())
715  ->output_corners(neighbours_file, "BLACK");
716  }
717 
718  // Loop over directions to find neighbours
719  // ---------------------------------------
720  for (int direction = L; direction <= R; direction++)
721  {
722  // Initialise difference in levels and coordinate offset
723  diff_level = 0;
724  s_diff = 0.0;
725 
726  // Find greater-or-equal-sized neighbour...
727  BinaryTree* neighb_pt = el_pt->gteq_edge_neighbour(
728  direction, s_in_neighbour, edge, diff_level, in_neighbouring_tree);
729 
730  // If neighbour exist and nodes are created: Doc it
731  if ((neighb_pt != 0) && (neighb_pt->object_pt()->nodes_built()))
732  {
733  // Doc neighbour stats
734  if (neighbours_txt_file.is_open())
735  {
736  neighbours_txt_file
737  << Direct_string[direction] << " neighbour of "
738  << el_pt->object_pt()->number() << " is "
739  << neighb_pt->object_pt()->number() << " diff_level "
740  << diff_level << " s_diff " << s_diff
741  << " inside neighbour the edge is " << Direct_string[edge]
742  << std::endl
743  << std::endl;
744  }
745 
746  // Plot neighbour in the appropriate colour
747  if (neighbours_file.is_open())
748  {
749  dynamic_cast<RefineableQElement<1>*>(neighb_pt->object_pt())
750  ->output_corners(neighbours_file, Colour[direction]);
751  }
752 
753  // Check that local coordinates in the larger element (obtained
754  // via s_diff) lead to the same spatial point as the node vertices
755  // in the current element
756  {
757  if (neighbours_file.is_open())
758  {
759  neighbours_file << "ZONE I=1 \n";
760  }
761 
762  // Left vertex:
763  // ------------
764 
765  // Get coordinates in large (neighbour) element
766  s[0] = s_in_neighbour[0];
767  neighb_pt->object_pt()->get_x(s, x_large);
768 
769  // Get coordinates in small element
770  Vector<double> s(1);
771  s[0] = S_base[direction];
772  el_pt->object_pt()->get_x(s, x_small);
773 
774  // Need to exclude periodic nodes from this check. There can
775  // only be periodic nodes if we have moved into the neighbour
776  bool is_periodic = false;
777  if (in_neighbouring_tree)
778  {
779  // Is the node periodic?
780  is_periodic =
781  el_pt->root_pt()->is_neighbour_periodic(direction);
782  }
783 
784  double error = 0.0;
785  // Only bother to calculate the error if the node is NOT periodic
786  if (is_periodic == false)
787  {
788  error += pow(x_small[0] - x_large[0], 2);
789  }
790 
791  // Take the root of the square error
792  error = sqrt(error);
793  if (neighbours_txt_file.is_open())
794  {
795  neighbours_txt_file << "Error (1) " << error << std::endl;
796  }
797 
798  if (std::fabs(error) > max_error)
799  {
801  }
802 
803  if (neighbours_file.is_open())
804  {
805  neighbours_file << x_large[0] << " 0 \n";
806  }
807 
808  // Right vertex:
809  // -------------
810 
811  // Get coordinates in large (neighbour) element
812  s[0] = s_in_neighbour[0];
813  neighb_pt->object_pt()->get_x(s, x_large);
814 
815  // Get coordinates in small element
816  s[0] = S_base[direction];
817  el_pt->object_pt()->get_x(s, x_small);
818 
819  error = 0.0;
820  // Only do this if we are NOT periodic
821  if (is_periodic == false)
822  {
823  error += pow(x_small[0] - x_large[0], 2);
824  }
825  // Take the root of the square error
826  error = sqrt(error);
827 
828  // error =
829  // sqrt(pow(x_small[0]-x_large[0],2)+pow(x_small[1]-x_large[1],2));
830  if (neighbours_txt_file.is_open())
831  {
832  neighbours_txt_file << "Error (2) " << error << std::endl;
833  }
834 
835  if (std::fabs(error) > max_error)
836  {
838  }
839 
840  if (neighbours_file.is_open())
841  {
842  neighbours_file << x_large[0] << " 0 \n";
843  }
844  }
845  // else
846  // {
847  // // No neighbour: write dummy zone so tecplot can find
848  // four
849  // // neighbours for every element
850  // if (neighbours_file.is_open())
851  // {
852  // neighbours_file << "ZONE I=1 \n";
853  // neighbours_file << "-0.05 -0.05 0 \n";
854  // neighbours_file << "-0.05 -0.05 0 \n";
855  // }
856  // }
857  }
858  // If neighbour does not exist: Insert blank zones into file
859  // so that tecplot can find four neighbours for every element
860  else
861  {
862  if (neighbours_file.is_open())
863  {
864  neighbours_file << "ZONE \n 0.00 0 \n";
865  neighbours_file << "ZONE I=1 \n";
866  neighbours_file << "-0.05 0 \n";
867  neighbours_file << "-0.05 0 \n";
868  }
869  }
870  }
871  } // End of case when element can be documented
872  }
873  }
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
MatrixXd L
Definition: LLT_example.cpp:6
@ R
Definition: StatisticsVector.h:21
static Vector< double > S_base
Definition: binary_tree.h:210
static Vector< std::string > Colour
Colours for neighbours in various directions.
Definition: binary_tree.h:206
static Vector< std::string > Direct_string
Translate (enumerated) directions into strings.
Definition: binary_tree.h:162
static const int OMEGA
Default value for an unassigned neighbour.
Definition: tree.h:262
RealScalar s
Definition: level1_cplx_impl.h:130
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
double max_error
Definition: MortaringCantileverCompareToNonMortaring.cpp:188
Real fabs(const Real &a)
Definition: boostmultiprec.cpp:117
int error
Definition: calibrate.py:297
list x
Definition: plotDoE.py:28

References calibrate::error, boost::multiprecision::fabs(), oomph::FiniteElement::get_x(), gteq_edge_neighbour(), i, oomph::TreeRoot::is_neighbour_periodic(), L, MeshRefinement::max_error, oomph::RefineableElement::nodes_built(), oomph::RefineableElement::number(), oomph::Tree::object_pt(), oomph::BinaryTreeNames::OMEGA, Eigen::bfloat16_impl::pow(), R, oomph::Tree::root_pt(), s, sqrt(), and plotDoE::x.

Referenced by oomph::BinaryTreeForest::check_all_neighbours(), self_test(), and oomph::BinaryTreeForest::self_test().

◆ gteq_edge_neighbour() [1/2]

BinaryTree * oomph::BinaryTree::gteq_edge_neighbour ( const int direction,
double s_diff,
int diff_level,
bool in_neighbouring_tree,
int  max_level,
BinaryTreeRoot *const &  orig_root_pt 
) const
private

Find greater or equal-sized edge neighbour in direction. Auxiliary internal routine which passes additional information around.

Find ‘greater-or-equal-sized edge neighbour’ in given direction (L/R).

This is an auxiliary routine which allows neighbour finding in adjacent binary trees. Needs to keep track of previous son types and the maximum level to which search is performed.

Parameters:

  • direction (L/R): Direction in which neighbour has to be found.
  • s_diff: Offset of left vertex from corresponding vertex in neighbour. Note that this is input/output as it needs to be incremented/decremented during the recursive calls to this function.
  • edge: We're looking for the neighbour across our edge 'direction' (L/R). When viewed from the neighbour, this edge is ‘edge’ (L/R). Since there is no relative rotation between neighbours this is a mere reflection, e.g. direction=L --> edge=R etc.
  • diff_level <= 0 indicates the difference in binary tree levels between the current element and its neighbour.
  • max_level is the maximum level to which the neighbour search is allowed to proceed. This is again necessary because in a forest, the neighbour search isn't based on pure recursion.
  • orig_root_pt identifies the root node of the element whose neighbour we're really trying to find by all these recursive calls.
264  {
265  using namespace BinaryTreeNames;
266 
267 #ifdef PARANOID
268  if ((direction != L) && (direction != R))
269  {
270  std::ostringstream error_stream;
271  error_stream << "Direction " << direction << " is not L or R"
272  << std::endl;
273 
274  throw OomphLibError(
275  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
276  }
277 #endif
278 
279  BinaryTree* next_el_pt;
280  BinaryTree* return_el_pt;
281 
282  // STEP 1: Find the neighbour's father
283  // -------
284 
285  // Does the element have a father?
286  if (Father_pt != 0)
287  {
288  // If the present segment (whose location inside its father element
289  // is specified by Son_type) is adjacent to the father's edge in the
290  // required direction, then its neighbour has a different father
291  // ---> we need to climb up the tree to the father and find his
292  // neighbour in the required direction. Note that this is the cunning
293  // recursive part. The returning may not stop until we hit the very
294  // top of the tree, when the element does NOT have a father.
295  if (Is_adjacent(direction, Son_type))
296  {
297  next_el_pt = dynamic_cast<BinaryTree*>(Father_pt)->gteq_edge_neighbour(
298  direction,
299  s_diff,
300  diff_level,
301  in_neighbouring_tree,
302  max_level,
303  orig_root_pt);
304  }
305  // If the present segment is not adjacent to the father's edge in the
306  // required direction, then the neighbour has the same father and is
307  // obtained by the appropriate reflection inside the father element.
308  // This will only be called if we have not left the original tree.
309  else
310  {
311  next_el_pt = dynamic_cast<BinaryTree*>(Father_pt);
312  }
313 
314  // We're about to ascend one level
315  diff_level -= 1;
316 
317  // Work out position of left corner of present edge in its father element
318  s_diff += pow(0.5, -diff_level);
319 
320  // STEP 2: We have now located the neighbour's father and need to
321  // ------- find the appropriate son.
322 
323  // Buffer cases where the neighbour (and hence its father) lie outside
324  // the boundary
325  if (next_el_pt != 0)
326  {
327  // If the father is a leaf then we can't descend to the same
328  // level as the present node ---> simply return the father himself
329  // as the (greater) neighbour. Same applies if we are about to
330  // descend lower than the max_level (in a neighbouring tree).
331  if ((next_el_pt->Son_pt.size() == 0) ||
332  (next_el_pt->Level > max_level - 1))
333  {
334  return_el_pt = next_el_pt;
335  }
336  // We have located the neighbour's father: The position of the
337  // neighbour is obtained by `reflecting' the position of the
338  // node itself. We know exactly how to reflect because we know which
339  // son type we are and we have the pointer to the neighbour's father.
340  else
341  {
342  int son_segment = Reflect(direction, Son_type);
343 
344  // The next element in the tree is the appropriate son of the
345  // neighbour's father
346  return_el_pt =
347  dynamic_cast<BinaryTree*>(next_el_pt->Son_pt[son_segment]);
348 
349  // Work out position of left corner of present edge in next
350  // higher element
351  s_diff -= pow(0.5, -diff_level);
352 
353  // We have just descended one level
354  diff_level += 1;
355  }
356  }
357  // The neighbour's father lies outside the boundary --> the neighbour
358  // itself does too --> return NULL
359  else
360  {
361  return_el_pt = 0;
362  }
363  }
364  // Element does not have a father --> check if it has a neighbouring
365  // tree in the appropriate direction
366  else
367  {
368  // Find neighbouring root
369  if (Root_pt->neighbour_pt(direction) != 0)
370  {
371  // In this case we have moved to a neighbour, so set the flag
372  in_neighbouring_tree = true;
373  return_el_pt =
374  dynamic_cast<BinaryTreeRoot*>(Root_pt->neighbour_pt(direction));
375  }
376  // No neighbouring tree, so there really is no neighbour --> return NULL
377  else
378  {
379  return_el_pt = 0;
380  }
381  }
382 
383  return return_el_pt;
384  }
static DenseMatrix< int > Reflect
Definition: binary_tree.h:221
BinaryTree * gteq_edge_neighbour(const int &direction, Vector< double > &s_in_neighbour, int &edge, int &diff_level, bool &in_neighbouring_tree) const
Definition: binary_tree.cc:172
static DenseMatrix< bool > Is_adjacent
Definition: binary_tree.h:217
TreeRoot *& neighbour_pt(const int &direction)
Definition: tree.h:357
Tree * Father_pt
Pointer to the Father of the Tree.
Definition: tree.h:296
TreeRoot * Root_pt
Pointer to the root of the tree.
Definition: tree.h:292
int Son_type
Son type (e.g. SW/SE/NW/NE in a quadtree)
Definition: tree.h:305

References oomph::Tree::Father_pt, gteq_edge_neighbour(), Is_adjacent, L, oomph::Tree::Level, oomph::TreeRoot::neighbour_pt(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, Eigen::bfloat16_impl::pow(), R, Reflect, oomph::Tree::Root_pt, oomph::Tree::Son_pt, and oomph::Tree::Son_type.

◆ gteq_edge_neighbour() [2/2]

BinaryTree * oomph::BinaryTree::gteq_edge_neighbour ( const int direction,
Vector< double > &  s_in_neighbour,
int edge,
int diff_level,
bool in_neighbouring_tree 
) const

Return pointer to greater or equal-sized edge neighbour in specified direction; also provide info regarding the relative size of the neighbour:

  • In the present binary tree, the left vertex is located at the local coordinate s = -1. This point is located at the local coordinate s = s_in_neighbour[0] in the neighbouring binary tree.
  • We're looking for a neighbour in the specified direction. When viewed from the neighbouring binary tree, the edge that separates the present binary tree from its neighbour is the neighbour's edge edge. Since in 1D there can be no rotation between the two binary trees, this is a simple reflection. For instance, if we're looking for a neighhbour in the L [eft] direction, edge will be R [ight].
  • diff_level <= 0 indicates the difference in refinement levels between the two neighbours. If diff_level==0, the neighbour has the same size as the current binary tree.
  • in_neighbouring_tree indicates whether the neighbour is actually in another tree in the forest. The introduction of this flag was necessitated by periodic problems where a TreeRoot can be its own neighbour.

Return pointer to greater or equal-sized edge neighbour in specified direction; also provide info regarding the relative size of the neighbour:

  • In the present binary tree, the left vertex is located at the local coordinate s = -1. This point is located at the local coordinate s = s_in_neighbour[0] in the neighbouring binary tree.
  • We're looking for a neighbour in the specified direction. When viewed from the neighbouring binary tree, the edge that separates the present binary tree from its neighbour is the neighbour's edge edge. Since in 1D there can be no rotation between the two binary trees, this is a simple reflection. For instance, if we're looking for a neighhbour in the L [eft] direction, edge will be R [ight].
  • diff_level <= 0 indicates the difference in refinement levels between the two neighbours. If diff_level==0, the neighbour has the same size as the current binary tree.
  • in_neighbouring_tree returns true if we have had to flip to a different root, even if that root is actually the same (as it can be in periodic problems).
177  {
178  using namespace BinaryTreeNames;
179 
180 #ifdef PARANOID
181  if ((direction != L) && (direction != R))
182  {
183  std::ostringstream error_stream;
184  error_stream << "Direction " << direction << " is not L or R"
185  << std::endl;
186 
187  throw OomphLibError(
188  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
189  }
190 #endif
191 
192  // Initialise in_neighbouring tree to false. It will be set to true
193  // during the recursion if we do actually hop over into the neighbour
194  in_neighbouring_tree = false;
195 
196  // Maximum level to which we're allowed to descend (we only want
197  // greater-or-equal-sized neighbours)
198  int max_level = Level;
199 
200  // Current element has the following root:
201  BinaryTreeRoot* orig_root_pt = dynamic_cast<BinaryTreeRoot*>(Root_pt);
202 
203  // Initialise offset in local coordinate
204  double s_diff = 0;
205 
206  // Initialise difference in level
207  diff_level = 0;
208 
209  // Find neighbour
210  BinaryTree* return_pt = gteq_edge_neighbour(direction,
211  s_diff,
212  diff_level,
213  in_neighbouring_tree,
214  max_level,
215  orig_root_pt);
216 
217  BinaryTree* neighb_pt = return_pt;
218 
219  // If neighbour exists...
220  if (neighb_pt != 0)
221  {
222  // What's the direction of the interfacial edge when viewed from within
223  // the neighbour element?
224  edge = Reflect_edge[direction];
225 
226  // What's the local coordinate s at which this edge is located in the
227  // neighbouring element?
228  s_in_neighbour[0] = S_base[edge];
229  }
230  return return_pt;
231  }
static Vector< int > Reflect_edge
Get opposite edge, e.g. Reflect_edge[L]=R.
Definition: binary_tree.h:213
int Level
Level of the Tree (level 0 = root)
Definition: tree.h:302

References L, oomph::Tree::Level, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, R, Reflect_edge, oomph::Tree::Root_pt, and S_base.

Referenced by oomph::RefineableQElement< 1 >::check_integrity(), doc_neighbours(), gteq_edge_neighbour(), and oomph::RefineableQElement< 1 >::node_created_by_neighbour().

◆ operator=()

void oomph::BinaryTree::operator= ( const BinaryTree )
delete

Broken assignment operator.

◆ self_test()

unsigned oomph::BinaryTree::self_test ( )

Self-test: Check all neighbours. Return success (0) if the maximum distance between corresponding points in the neighbours is less than the tolerance specified in the static value BinaryTree::Max_neighbour_finding_tolerance.

Self-test: Check neighbour finding routine. For each element in the tree and for each vertex, determine the distance between the vertex and its position in the neighbour. If the difference is less than Tree::Max_neighbour_finding_tolerance return success (0), otherwise failure (1).

394  {
395  // Stick pointers to all nodes into Vector and number elements
396  // in the process
397  Vector<Tree*> all_nodes_pt;
398  stick_all_tree_nodes_into_vector(all_nodes_pt);
399  long int count = 0;
400  unsigned long num_nodes = all_nodes_pt.size();
401  for (unsigned long i = 0; i < num_nodes; i++)
402  {
403  all_nodes_pt[i]->object_pt()->set_number(++count);
404  }
405 
406  // Check neighbours (distance between hanging nodes) -- don't print
407  // (keep output streams closed)
408  double max_error = 0.0;
409  std::ofstream neighbours_file;
410  std::ofstream neighbours_txt_file;
412  all_nodes_pt, neighbours_file, neighbours_txt_file, max_error);
413 
415  {
416  oomph_info << "\n \n Failed self_test() for BinaryTree: Max. error "
417  << max_error << std::endl
418  << std::endl;
419  return 1;
420  }
421  else
422  {
423  oomph_info << "\n \n Passed self_test() for BinaryTree: Max. error "
424  << max_error << std::endl
425  << std::endl;
426  return 0;
427  }
428  }
static void doc_neighbours(Vector< Tree * > forest_nodes_pt, std::ofstream &neighbours_file, std::ofstream &neighbours_txt_file, double &max_error)
Definition: binary_tree.cc:668
void stick_all_tree_nodes_into_vector(Vector< Tree * > &)
Traverse and stick pointers to all "nodes" into Vector.
Definition: tree.cc:277
static double Max_neighbour_finding_tolerance
Definition: tree.h:313
OomphInfo oomph_info
Definition: oomph_definitions.cc:319

References doc_neighbours(), i, MeshRefinement::max_error, oomph::Tree::Max_neighbour_finding_tolerance, oomph::oomph_info, and oomph::Tree::stick_all_tree_nodes_into_vector().

◆ setup_static_data()

void oomph::BinaryTree::setup_static_data ( )
static

Set up the static data, reflection schemes, etc.

Set up the static data stored in the BinaryTree – this needs to be called before BinaryTrees can be used. Automatically called by RefineableLineMesh constructor.

87  {
88  using namespace BinaryTreeNames;
89 
90 #ifdef PARANOID
92  {
93  std::ostringstream error_stream;
94  error_stream << "Inconsistent enumeration! \n Tree::OMEGA="
95  << Tree::OMEGA << "\nBinaryTree::OMEGA=" << BinaryTree::OMEGA
96  << std::endl;
97  throw OomphLibError(
99  }
100 #endif
101 
102  // Set flag to indicate that static data has been setup
104 
105  // Tecplot colours for neighbours in various directions
106  Colour.resize(27);
107 
108  Colour[L] = "RED";
109  Colour[R] = "CYAN";
110  Colour[OMEGA] = "YELLOW";
111 
112  // S_base(direction): Initial value for coordinate s on the
113  // edge indicated by direction (L/R)
114  S_base.resize(27);
115 
116  S_base[L] = -1.0;
117  S_base[R] = 1.0;
118 
119  // Translate (enumerated) directions into strings
120  Direct_string.resize(27);
121 
122  Direct_string[L] = "L";
123  Direct_string[R] = "R";
124  Direct_string[OMEGA] = "OMEGA";
125 
126  // Build direction/segment adjacency scheme:
127  // Is_adjacent(i_vertex,j_segment): Is vertex adjacent to segment?
128  Is_adjacent.resize(27, 27);
129 
130  Is_adjacent(L, L) = true;
131  Is_adjacent(R, L) = false;
132  Is_adjacent(L, R) = false;
133  Is_adjacent(R, R) = true;
134 
135  // Build reflection scheme: Reflect(direction,segment):
136  // Get mirror of segment in direction
137  Reflect.resize(27, 27);
138 
139  Reflect(L, L) = R;
140  Reflect(R, L) = R;
141  Reflect(L, R) = L;
142  Reflect(R, R) = L;
143 
144  // Get opposite edge, e.g. Reflect_edge(L)=R
145  Reflect_edge.resize(27);
146 
147  Reflect_edge[L] = R;
148  Reflect_edge[R] = L;
149  }
static bool Static_data_has_been_setup
Boolean indicating that static member data has been setup.
Definition: binary_tree.h:193
void resize(const unsigned long &n)
Definition: matrices.h:498

References Colour, Direct_string, Is_adjacent, L, oomph::Tree::OMEGA, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, R, Reflect, Reflect_edge, oomph::DenseMatrix< T >::resize(), S_base, and Static_data_has_been_setup.

Referenced by oomph::RefineableLineMesh< ELEMENT >::RefineableLineMesh().

Member Data Documentation

◆ Colour

Vector< std::string > oomph::BinaryTree::Colour
staticprivate

Colours for neighbours in various directions.

Colours for neighbours in various directions (static data).

Referenced by setup_static_data().

◆ Direct_string

Vector< std::string > oomph::BinaryTree::Direct_string
static

Translate (enumerated) directions into strings.

Translate (enumerated) directions into strings (static data).

Referenced by setup_static_data().

◆ Is_adjacent

DenseMatrix< bool > oomph::BinaryTree::Is_adjacent
staticprivate

Array of direction/segment adjacency scheme: Is_adjacent(i_vertex,j_segment): Is vertex adjacent to segment?

Array of direction/segment adjacency scheme: Is_adjacent(i_vertex,j_segment): Is vertex adjacent to segment? (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ Reflect

DenseMatrix< int > oomph::BinaryTree::Reflect
staticprivate

Reflection scheme: Reflect(direction,segment): Get mirror of segment in specified direction. E.g. Reflect(L,L)=R.

Reflection scheme: Reflect(direction,segment): Get mirror of segment in specified direction. E.g. Reflect(L,L)=R (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ Reflect_edge

Vector< int > oomph::BinaryTree::Reflect_edge
staticprivate

Get opposite edge, e.g. Reflect_edge[L]=R.

Get opposite edge, e.g. Reflect_edge[N]=S (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ S_base

Vector< double > oomph::BinaryTree::S_base
staticprivate

S_base(direction): Initial value for coordinate s on the edge indicated by direction (L/R)

S_base(direction): Initial value for coordinate s on the edge indicated by direction (L/R) (static data).

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ Static_data_has_been_setup

bool oomph::BinaryTree::Static_data_has_been_setup = false
staticprotected

Boolean indicating that static member data has been setup.

Referenced by oomph::BinaryTreeRoot::BinaryTreeRoot(), and setup_static_data().


The documentation for this class was generated from the following files: