oomph::QuadTree Class Reference

#include <quadtree.h>

+ Inheritance diagram for oomph::QuadTree:

Public Member Functions

virtual ~QuadTree ()
 
 QuadTree (const QuadTree &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const QuadTree &)=delete
 Broken assignment operator. More...
 
Treeconstruct_son (RefineableElement *const &object_pt, Tree *const &father_pt, const int &son_type)
 
QuadTreegteq_edge_neighbour (const int &direction, Vector< unsigned > &translate_s, Vector< double > &s_lo, Vector< double > &s_hi, int &edge, int &diff_level, bool &in_neighbouring_tree) const
 
void stick_neighbouring_leaves_into_vector (Vector< const QuadTree * > &tree_neighbouring_nodes, Vector< Vector< double >> &tree_neighbouring_s_lo, Vector< Vector< double >> &tree_neighbouring_s_hi, Vector< int > &tree_neighbouring_diff_level, const QuadTree *my_neigh_pt, const int &direction) 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 ()
 Setup the static data, rotation and 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

 QuadTree ()
 Default constructor (empty and broken) More...
 
 QuadTree (RefineableElement *const &object_pt)
 
 QuadTree (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
 Bool 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

QuadTreegteq_edge_neighbour (const int &direction, double &s_diff, int &diff_level, bool &in_neighbouring_tree, int max_level, QuadTreeRoot *const &orig_root_pt) const
 

Static Private Attributes

static Vector< std::string > Colour
 Colours for neighbours in various directions. More...
 
static DenseMatrix< doubleS_base
 
static DenseMatrix< doubleS_step
 
static Vector< intReflect_edge
 Get opposite edge, e.g. Reflect_edge[N]=S. More...
 
static DenseMatrix< boolIs_adjacent
 
static DenseMatrix< intReflect
 
static DenseMatrix< intRotate
 
static DenseMatrix< intRotate_angle
 
static DenseMatrix< intS_direct
 

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

QuadTree class: Recursively defined, generalised quadtree.

A QuadTree has:

  • a pointer to the object (of type RefineableQElement<2>) that it represents in a mesh refinement context.
  • Vector of pointers to its four (SW/SE/NW/NE) sons (which are themselves quadtrees). If the Vector of pointers to the sons has zero length, the QuadTree is a "leaf node" in the overall quadtree.
  • a pointer to its father. If this pointer is NULL, the QuadTree is the the root node of the overall quadtree. 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 quadtrees.

The objects contained in the quadtree are assumed to be (topologically) rectangular elements whose geometry is parametrised by local coordinates \( {\bf s} \in [-1,1]^2 \).

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 QuadTrees are only generated by splitting existing QuadTrees. Therefore, the constructors are protected. The only QuadTree that "Joe User" can create is the (derived) class QuadTreeRoot.

Constructor & Destructor Documentation

◆ ~QuadTree()

virtual oomph::QuadTree::~QuadTree ( )
inlinevirtual

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

108 {}

◆ QuadTree() [1/4]

oomph::QuadTree::QuadTree ( const QuadTree dummy)
delete

Broken copy constructor.

◆ QuadTree() [2/4]

oomph::QuadTree::QuadTree ( )
inlineprotected

Default constructor (empty and broken)

204  {
205  throw OomphLibError(
206  "Don't call an empty constructor for a QuadTree object",
209  }
#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().

◆ QuadTree() [3/4]

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

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

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

◆ QuadTree() [4/4]

oomph::QuadTree::QuadTree ( 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 (SE/SW/NE/NW) it is. Protected because QuadTrees can only be created internally, during the split operation. Only QuadTreeRoots can be created externally.

228  {
229  }
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::QuadTree::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 QuadTree and not a general Tree.

Implements oomph::Tree.

121  {
122  QuadTree* temp_quad_pt = new QuadTree(object_pt, father_pt, son_type);
123  return temp_quad_pt;
124  }
QuadTree()
Default constructor (empty and broken)
Definition: quadtree.h:203

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

◆ doc_neighbours()

void oomph::QuadTree::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 quadtree (nodes) contained in the Vector forest_node_pt. Output into neighbours_file which can be viewed from tecplot with QuadTreeNeighbours.mcr Neighbour info and errors are displayed on neighbours_txt_file. Finally, compute the max. error between vertices when viewed from neighhbouring element. If the two filestreams are closed, output is suppressed.

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

1406  {
1407  using namespace QuadTreeNames;
1408 
1409  int diff_level;
1410  double s_diff;
1411  bool in_neighbouring_tree;
1412  int edge = OMEGA;
1413 
1414  Vector<double> s(2);
1415  Vector<double> x(2);
1416  Vector<int> prev_son_type;
1417 
1418  Vector<unsigned> translate_s(2);
1419  Vector<double> s_lo(2);
1420  Vector<double> s_hi(2);
1421 
1422  Vector<double> x_small(2);
1423  Vector<double> x_large(2);
1424 
1425  // Initialise error in vertex positions
1426  max_error = 0.0;
1427 
1428 
1429  // Loop over all elements to assign numbers for plotting
1430  // -----------------------------------------------------
1431  unsigned long num_nodes = forest_nodes_pt.size();
1432  for (unsigned long i = 0; i < num_nodes; i++)
1433  {
1434  // Set number
1435  forest_nodes_pt[i]->object_pt()->set_number(i);
1436  }
1437 
1438  // Loop over all elements for checks
1439  // ---------------------------------
1440  for (unsigned long i = 0; i < num_nodes; i++)
1441  {
1442  // Doc the element itself
1443  QuadTree* el_pt = dynamic_cast<QuadTree*>(forest_nodes_pt[i]);
1444 
1445  // If the object is incomplete complain
1446  if (el_pt->object_pt()->nodes_built())
1447  {
1448  // Print it
1449  if (neighbours_file.is_open())
1450  {
1451  dynamic_cast<RefineableQElement<2>*>(el_pt->object_pt())
1452  ->output_corners(neighbours_file, "BLACK");
1453  }
1454 
1455  // Loop over directions to find neighbours
1456  // ----------------------------------------
1457  for (int direction = N; direction <= W; direction++)
1458  {
1459  // Initialise difference in levels and coordinate offset
1460  diff_level = 0;
1461  s_diff = 0.0;
1462 
1463  // Find greater-or-equal-sized neighbour...
1464  QuadTree* neighb_pt =
1465  el_pt->gteq_edge_neighbour(direction,
1466  translate_s,
1467  s_lo,
1468  s_hi,
1469  edge,
1470  diff_level,
1471  in_neighbouring_tree);
1472 
1473  // If neighbour exist and nodes are created: Doc it
1474  if ((neighb_pt != 0) && (neighb_pt->object_pt()->nodes_built()))
1475  {
1476  // Doc neighbour stats
1477  if (neighbours_txt_file.is_open())
1478  {
1479  neighbours_txt_file
1480  << Direct_string[direction] << " neighbour of "
1481  << el_pt->object_pt()->number() << " is "
1482  << neighb_pt->object_pt()->number() << " diff_level "
1483  << diff_level << " s_diff " << s_diff
1484  << " inside neighbour the edge is " << Direct_string[edge]
1485  << std::endl
1486  << std::endl;
1487  }
1488 
1489  // Plot neighbour in the appropriate Colour
1490  if (neighbours_file.is_open())
1491  {
1492  dynamic_cast<RefineableQElement<2>*>(neighb_pt->object_pt())
1493  ->output_corners(neighbours_file, Colour[direction]);
1494  }
1495 
1496  // Check that local
1497  // coordinates in the larger element (obtained via s_diff)
1498  // lead to the same spatial point as the node vertices
1499  // in the current element
1500  {
1501  if (neighbours_file.is_open())
1502  {
1503  neighbours_file << "ZONE I=2 \n";
1504  }
1505 
1506  // (Lower)/(left) vertex:
1507  //-----------------------
1508 
1509  // Get coordinates in large (neighbour) element
1510  s[0] = s_lo[0];
1511  s[1] = s_lo[1];
1512  neighb_pt->object_pt()->get_x(s, x_large);
1513 
1514  // Get coordinates in small element
1515  Vector<double> s(2);
1516  s[0] = S_base(0, direction);
1517  s[1] = S_base(1, direction);
1518  el_pt->object_pt()->get_x(s, x_small);
1519 
1520 
1521  // Need to exclude periodic nodes from this check
1522  // There can only be periodic nodes if we have moved into the
1523  // neighbour
1524  bool is_periodic = false;
1525  if (in_neighbouring_tree)
1526  {
1527  // is the node periodic
1528  is_periodic =
1529  el_pt->root_pt()->is_neighbour_periodic(direction);
1530  }
1531 
1532  double error = 0.0;
1533  // Only bother to calculate the error if the node is NOT periodic
1534  if (is_periodic == false)
1535  {
1536  for (int i = 0; i < 2; i++)
1537  {
1538  error += pow(x_small[i] - x_large[i], 2);
1539  }
1540  }
1541 
1542  // Take the root of the square error
1543  error = sqrt(error);
1544  if (neighbours_txt_file.is_open())
1545  {
1546  neighbours_txt_file << "Error (1) " << error << std::endl;
1547  }
1548 
1549  if (std::fabs(error) > max_error)
1550  {
1552  }
1553 
1554  if (neighbours_file.is_open())
1555  {
1556  neighbours_file << x_large[0] << " " << x_large[1] << " 0 \n";
1557  }
1558 
1559  // (Upper)/(right) vertex:
1560  //------------------------
1561 
1562  // Get coordinates in large (neighbour) element
1563  s[0] = s_hi[0];
1564  s[1] = s_hi[1];
1565  neighb_pt->object_pt()->get_x(s, x_large);
1566 
1567  // Get coordinates in small element
1568  s[0] = S_base(0, direction) + S_step(0, direction);
1569  s[1] = S_base(1, direction) + S_step(1, direction);
1570  el_pt->object_pt()->get_x(s, x_small);
1571 
1572  error = 0.0;
1573  // Only do this if we are NOT periodic
1574  if (is_periodic == false)
1575  {
1576  for (int i = 0; i < 2; i++)
1577  {
1578  error += pow(x_small[i] - x_large[i], 2);
1579  }
1580  }
1581  // Take the root of the square error
1582  error = sqrt(error);
1583 
1584  // error=
1585  // sqrt(pow(x_small[0]-x_large[0],2)+pow(x_small[1]-x_large[1],2));
1586  if (neighbours_txt_file.is_open())
1587  {
1588  neighbours_txt_file << "Error (2) " << error << std::endl;
1589  }
1590 
1591  if (std::fabs(error) > max_error)
1592  {
1594  }
1595 
1596  if (neighbours_file.is_open())
1597  {
1598  neighbours_file << x_large[0] << " " << x_large[1] << " 0 \n";
1599  }
1600  }
1601  // else
1602  // {
1603  // // No neighbour: write dummy zone so tecplot can find
1604  // four
1605  // // neighbours for every element
1606  // if (neighbours_file.is_open())
1607  // {
1608  // neighbours_file << "ZONE I=2 \n";
1609  // neighbours_file << "-0.05 -0.05 0 \n";
1610  // neighbours_file << "-0.05 -0.05 0 \n";
1611  // }
1612  // }
1613  }
1614  // If neighbour does not exist: Insert blank zones into file
1615  // so that tecplot can find four neighbours for every element
1616  else
1617  {
1618  if (neighbours_file.is_open())
1619  {
1620  neighbours_file << "ZONE \n 0.00 0.00 0 \n";
1621  neighbours_file << "ZONE I=2 \n";
1622  neighbours_file << "-0.05 -0.05 0 \n";
1623  neighbours_file << "-0.05 -0.05 0 \n";
1624  }
1625  }
1626  }
1627  } // End of case when element can be documented
1628  }
1629  }
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
static Vector< std::string > Direct_string
Translate (enumerated) directions into strings.
Definition: quadtree.h:199
static DenseMatrix< double > S_step
Definition: quadtree.h:255
static DenseMatrix< double > S_base
Definition: quadtree.h:250
static Vector< std::string > Colour
Colours for neighbours in various directions.
Definition: quadtree.h:246
static const int OMEGA
Default value for an unassigned neighbour.
Definition: tree.h:262
@ N
Definition: constructor.cpp:22
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
@ W
Definition: quadtree.h:63
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(), MeshRefinement::max_error, N, oomph::RefineableElement::nodes_built(), oomph::RefineableElement::number(), oomph::Tree::object_pt(), oomph::BinaryTreeNames::OMEGA, Eigen::bfloat16_impl::pow(), oomph::Tree::root_pt(), s, sqrt(), oomph::QuadTreeNames::W, and plotDoE::x.

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

◆ gteq_edge_neighbour() [1/2]

QuadTree * oomph::QuadTree::gteq_edge_neighbour ( const int direction,
double s_diff,
int diff_level,
bool in_neighbouring_tree,
int  max_level,
QuadTreeRoot *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 (N/E/S/W).

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

Parameters:

  • direction: N/S/E/W: Direction in which neighbour has to be found.
  • s_diff: Offset of lower/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' (N/S/E/W). When viewed from the neighbour, this edge is ‘edge’ (N/S/E/W). [If there's no relative rotation between neighbours then this is a mere reflection, e.g. direction=N --> edge=S etc.]
  • diff_level <= 0 indicates the difference in quadtree 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.
608  {
609  using namespace QuadTreeNames;
610 
611 #ifdef PARANOID
612  if ((direction != S) && (direction != E) && (direction != N) &&
613  (direction != W))
614  {
615  std::ostringstream error_stream;
616  error_stream << "Direction " << direction << " is not N, S, E, W"
617  << std::endl;
618 
619  throw OomphLibError(
620  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
621  }
622 #endif
623 
624  QuadTree* next_el_pt;
625  QuadTree* return_el_pt;
626 
627  // STEP 1: Find the neighbour's father
628  //--------
629 
630  // Does the element have a father?
631  if (Father_pt != 0)
632  {
633  // If the present quadrant (whose location inside its
634  // father element is specified by Son_type) is adjacent to the
635  // father's edge in the required direction, then its neighbour has
636  // a different father ---> we need to climb up the tree to
637  // the father and find his neighbour in the required direction
638 
639  // Note that this is the cunning recursive part. The returning may not
640  // stop until we hit the very top of the tree, when the element does NOT
641  // have a father
642  if (Is_adjacent(direction, Son_type))
643  {
644  next_el_pt = dynamic_cast<QuadTree*>(Father_pt)->gteq_edge_neighbour(
645  direction,
646  s_diff,
647  diff_level,
648  in_neighbouring_tree,
649  max_level,
650  orig_root_pt);
651  }
652  // If the present quadrant is not adjacent to the
653  // father's edge in the required direction, then the
654  // neighbour has the same father and is obtained
655  // by the appropriate reflection inside the father element
656  // This will only be called if we have not left the original tree.
657  else
658  {
659  next_el_pt = dynamic_cast<QuadTree*>(Father_pt);
660  }
661 
662  // We're about to ascend one level:
663  diff_level -= 1;
664 
665  // Work out position of lower (or left) corner of present edge
666  // in its father element
667  s_diff += pow(0.5, -diff_level) * S_direct(direction, Son_type);
668 
669  // STEP 2: We have now located the neighbour's father and need to
670  // ------- find the appropriate son.
671 
672  // Buffer cases where the neighbour (and hence its father) lie outside
673  // the boundary
674  if (next_el_pt != 0)
675  {
676  // If the father is a leaf then we can't descend to the same
677  // level as the present node ---> simply return the father himself
678  // as the (greater) neighbour. Same applies if we are about
679  // to descend lower than the max_level (in a neighbouring tree)
680  if ((next_el_pt->Son_pt.size() == 0) ||
681  (next_el_pt->Level > max_level - 1))
682  {
683  return_el_pt = next_el_pt;
684  }
685  // We have located the neighbour's father: The position of the
686  // neighbour is obtained by `reflecting' the position of the
687  // node itself.
688 
689  // We know exactly how to reflect, because we know which son type we
690  // are and we have the pointer to the neighbours father
691  else
692  {
693  int son_quadrant = Reflect(direction, Son_type);
694 
695  // If the root of the neighbour's father is not our root, we
696  // might need to rotate
697  if (orig_root_pt != next_el_pt->Root_pt)
698  {
699  // Get the north equivalent of the next element
700  int my_north =
701  dynamic_cast<QuadTreeRoot*>(Root_pt)->north_equivalent(direction);
702  son_quadrant = Rotate(my_north, son_quadrant);
703  }
704 
705  // The next element in the tree is the appropriate son of the
706  // neighbour's father
707  return_el_pt =
708  dynamic_cast<QuadTree*>(next_el_pt->Son_pt[son_quadrant]);
709 
710  // Work out position of lower (or left) corner of present edge
711  // in next higher element
712  s_diff -= pow(0.5, -diff_level) * S_direct(direction, Son_type);
713 
714  // We have just descended one level
715  diff_level += 1;
716  }
717  }
718  // The neighbour's father lies outside the boundary --> the neighbour
719  // itself does too --> return NULL.
720  else
721  {
722  return_el_pt = 0;
723  }
724  }
725  // Element does not have a father --> check if it has a neighbouring
726  // tree in the appropriate direction
727  else
728  {
729  // Find neighbouring root
730  if (Root_pt->neighbour_pt(direction) != 0)
731  {
732  // In this case we have moved to a neighbour, so set the flag
733  in_neighbouring_tree = true;
734  return_el_pt =
735  dynamic_cast<QuadTreeRoot*>(Root_pt->neighbour_pt(direction));
736  }
737  // No neighbouring tree, so there really is no neighbour --> return NULL
738  else
739  {
740  return_el_pt = 0;
741  }
742  }
743 
744  return return_el_pt;
745  }
static DenseMatrix< int > Reflect
Definition: quadtree.h:267
static DenseMatrix< int > Rotate
Definition: quadtree.h:271
static DenseMatrix< int > S_direct
Definition: quadtree.h:282
QuadTree * gteq_edge_neighbour(const int &direction, Vector< unsigned > &translate_s, Vector< double > &s_lo, Vector< double > &s_hi, int &edge, int &diff_level, bool &in_neighbouring_tree) const
Definition: quadtree.cc:413
static DenseMatrix< bool > Is_adjacent
Definition: quadtree.h:263
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
double E
Elastic modulus.
Definition: TwenteMeshGluing.cpp:68
@ S
Definition: quadtree.h:62

References Global_Physical_Variables::E, oomph::Tree::Father_pt, gteq_edge_neighbour(), Is_adjacent, oomph::Tree::Level, N, oomph::TreeRoot::neighbour_pt(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, Eigen::bfloat16_impl::pow(), Reflect, oomph::Tree::Root_pt, Rotate, oomph::QuadTreeNames::S, S_direct, oomph::Tree::Son_pt, oomph::Tree::Son_type, and oomph::QuadTreeNames::W.

◆ gteq_edge_neighbour() [2/2]

QuadTree * oomph::QuadTree::gteq_edge_neighbour ( const int direction,
Vector< unsigned > &  translate_s,
Vector< double > &  s_lo,
Vector< double > &  s_hi,
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 and orientation of neighbour:

  • The vector translate_s turns the index of the local coordinate in the present quadtree into that of the neighbour. If there are no rotations then translate_s[i] = i, but if, for example, the neighbour's eastern face is adjacent to our northern face translate_s[0] = 1 and translate_s[1] = 0. Of course, this could be deduced after the fact, but it's easier to do it here.
  • In the present quadtree, the lower left (south west) vertex is located at local coordinates (-1,-1). This point is located at the local coordinates (s_lo[0], s_lo[1]) in the neighbouring quadtree.
  • ditto with s_hi: In the present quadtree, the upper right (north east) vertex is located at local coordinates (1,1). This point is located at the local coordinates (s_hi[0], s_hi[1]) in the neighbouring quadtree.
  • We're looking for a neighbour in the specified direction. When viewed from the neighbouring quadtree, the edge that separates the present quadtree from its neighbour is the neighbour's edge edge. If there's no rotation between the two quadtrees, this is a simple reflection: For instance, if we're looking for a neighhbour in the N [orthern] direction, edge will be S [outh]
  • 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 quadtree.
  • 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 and orientation of neighbour:

  • The vector translate_s turns the index of the local coordinate in the present quadtree into that of the neighbour. If there are no rotations then translate_s[i] = i, but if, for example, the neighbour's eastern face is adjacent to our northern face translate_s[0] = 1 and translate_s[1] = 0. Of course, this could be deduced after the fact, but it's easier to do it here.
  • Let's have a look at the current quadtree's edge in the specified direction. The edge will be parallel to one of the two local coordinates in the element. This edge has two vertices. The vertex at the minimum value of the local coordinate (the "lo" vertex) is located at the local coordinates (s_lo[0], s_lo[1]) in the neighbouring quadtree.
  • ditto with s_hi: The vertex at the maximum value of the local coordinate located at the local coordinates (s_hi[0], s_hi[1]) in the neighbouring quadtree.
  • We're looking for a neighbour in the specified direction. When viewed from the neighbouring quadtree, the edge that separates the present quadtree from its neighbour is the neighbour's edge edge. If there's no rotation between the two quadtrees, this is a simple reflection: For instance, if we're looking for a neighhbour in the N [orthern] direction, edge will be S [outh]
  • 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 quadtree.
  • in_neighbouring_tree returns true is we have had to flip to a different root, even if that root is actually the same as it can be in periodic problems.
420  {
421  using namespace QuadTreeNames;
422 
423 #ifdef PARANOID
424  if ((direction != S) && (direction != E) && (direction != N) &&
425  (direction != W))
426  {
427  std::ostringstream error_stream;
428  error_stream << "Direction " << direction << " is not N, S, E, W"
429  << std::endl;
430 
431  throw OomphLibError(
432  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
433  }
434 #endif
435 
436  // Initialise in_neighbouring tree to false. It will be set to true
437  // during the recursion if we do actually hop over in to the neighbour
438  in_neighbouring_tree = false;
439 
440  // Maximum level to which we're allowed to descend (we only want
441  // greater-or-equal-sized neighbours)
442  int max_level = Level;
443 
444  // Current element has the following root:
445  QuadTreeRoot* orig_root_pt = dynamic_cast<QuadTreeRoot*>(Root_pt);
446 
447  // Initialise offset in local coordinate
448  double s_diff = 0;
449 
450  // Initialise difference in level
451  diff_level = 0;
452 
453  // Find neighbour
454  QuadTree* return_pt = gteq_edge_neighbour(direction,
455  s_diff,
456  diff_level,
457  in_neighbouring_tree,
458  max_level,
459  orig_root_pt);
460 
461  QuadTree* neighb_pt = return_pt;
462 
463  // If neighbour exists: What's the direction of the interfacial
464  // edge when viewed from within the neighbour element?
465  if (neighb_pt != 0)
466  {
467  // Rotate things around (the orientation of N in the neighbour might be
468  // be different from that in the present element)
469  // Initialise the direction
470  int new_dir = direction;
471  // If the neighbour has a different root, then there could be a possible
472  // rotation, find it
473  if (neighb_pt->root_pt() != Root_pt)
474  {
475  new_dir = Rotate(orig_root_pt->north_equivalent(direction), direction);
476  }
477 
478  s_lo[0] = S_base(0, Reflect_edge[new_dir]) +
479  S_step(0, Reflect_edge[new_dir]) * s_diff;
480  s_lo[1] = S_base(1, Reflect_edge[new_dir]) +
481  S_step(1, Reflect_edge[new_dir]) * s_diff;
482 
483  s_hi[0] = S_base(0, Reflect_edge[new_dir]) +
484  S_step(0, Reflect_edge[new_dir]) * pow(2.0, diff_level) +
485  S_step(0, Reflect_edge[new_dir]) * s_diff;
486  s_hi[1] = S_base(1, Reflect_edge[new_dir]) +
487  S_step(1, Reflect_edge[new_dir]) * pow(2.0, diff_level) +
488  S_step(1, Reflect_edge[new_dir]) * s_diff;
489 
490  Vector<double> s_lo_new(2), s_hi_new(2);
491 
492  // What's the direction of the interfacial edge when viewed from within
493  // the neighbour element?
494  edge = Reflect_edge[new_dir];
495 
496  // Set up the translation scheme for the local coordinates
497  {
498  bool swap = false;
499  // Do we need to switch the coordinate
500  switch (direction)
501  {
502  // If the direction is north or south,
503  // but the neighbour's coordinate s[1] is not constant, we must swap
504  case N:
505  case S:
506  if (s_lo[1] != s_hi[1])
507  {
508  swap = true;
509  }
510  break;
511  // If the direction is east or west
512  // but the neighbour's corodinate s[0] is not constant, we must swap
513  case E:
514  case W:
515  if (s_lo[0] != s_hi[0])
516  {
517  swap = true;
518  }
519  break;
520  // Catch all totally un-necessary
521  default:
522  std::ostringstream error_stream;
523  error_stream << "Direction " << direction << " is not N, S, E, W"
524  << std::endl;
525 
526  throw OomphLibError(error_stream.str(),
529  }
530 
531  // If we must swap, then do so
532  if (swap)
533  {
534  translate_s[0] = 1;
535  translate_s[1] = 0;
536  }
537  // Othewise, it's just a straight translation
538  else
539  {
540  translate_s[0] = 0;
541  translate_s[1] = 1;
542  }
543  }
544 
545  // Reverse directions?
546  s_lo_new[0] = s_lo[0];
547  s_lo_new[1] = s_lo[1];
548  s_hi_new[0] = s_hi[0];
549  s_hi_new[1] = s_hi[1];
550 
551  if (((edge == N) || (edge == S)) &&
552  ((Rotate_angle(direction, new_dir) == 90) ||
553  (Rotate_angle(direction, new_dir) == 180)))
554  {
555  s_lo_new[0] = -s_lo[0];
556  s_hi_new[0] = -s_hi[0];
557  }
558  if (((edge == E) || (edge == W)) &&
559  ((Rotate_angle(direction, new_dir) == 270) ||
560  (Rotate_angle(direction, new_dir) == 180)))
561  {
562  s_lo_new[1] = -s_lo[1];
563  s_hi_new[1] = -s_hi[1];
564  }
565 
566  s_lo[0] = s_lo_new[0];
567  s_lo[1] = s_lo_new[1];
568  s_hi[0] = s_hi_new[0];
569  s_hi[1] = s_hi_new[1];
570  }
571  return return_pt;
572  }
static Vector< int > Reflect_edge
Get opposite edge, e.g. Reflect_edge[N]=S.
Definition: quadtree.h:258
static DenseMatrix< int > Rotate_angle
Definition: quadtree.h:277
int Level
Level of the Tree (level 0 = root)
Definition: tree.h:302
EIGEN_BLAS_FUNC() swap(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Definition: level1_impl.h:117

References Global_Physical_Variables::E, oomph::Tree::Level, N, oomph::QuadTreeRoot::north_equivalent(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, Eigen::bfloat16_impl::pow(), Reflect_edge, oomph::Tree::root_pt(), oomph::Tree::Root_pt, Rotate, Rotate_angle, oomph::QuadTreeNames::S, S_base, S_step, swap(), and oomph::QuadTreeNames::W.

Referenced by oomph::PRefineableQElement< 2, INITIAL_NNODE_1D >::check_integrity(), oomph::RefineableQElement< 2 >::check_integrity(), doc_neighbours(), gteq_edge_neighbour(), oomph::PRefineableQElement< 2, INITIAL_NNODE_1D >::node_created_by_neighbour(), oomph::RefineableQElement< 2 >::node_created_by_neighbour(), oomph::PRefineableQElement< 2, INITIAL_NNODE_1D >::node_created_by_son_of_neighbour(), oomph::PRefineableQElement< 2, INITIAL_NNODE_1D >::quad_hang_helper(), oomph::RefineableQElement< 2 >::quad_hang_helper(), and stick_neighbouring_leaves_into_vector().

◆ operator=()

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

Broken assignment operator.

◆ self_test()

unsigned oomph::QuadTree::self_test ( )

Self-test: Check all neighbours. Return success (0) if the max. distance between corresponding points in the neighbours is less than the tolerance specified in the static value QuadTree::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 neigbour. If the difference is less than Tree::Max_neighbour_finding_tolerance. return success (0), otherwise failure (1)

815  {
816  // Stick pointers to all nodes into Vector and number elements
817  // in the process
818  Vector<Tree*> all_nodes_pt;
819  stick_all_tree_nodes_into_vector(all_nodes_pt);
820  long int count = 0;
821  unsigned long num_nodes = all_nodes_pt.size();
822  for (unsigned long i = 0; i < num_nodes; i++)
823  {
824  all_nodes_pt[i]->object_pt()->set_number(++count);
825  }
826 
827  // Check neighbours (distance between hanging nodes) -- don't print (keep
828  // output streams closed)
829  double max_error = 0.0;
830  std::ofstream neighbours_file;
831  std::ofstream neighbours_txt_file;
833  all_nodes_pt, neighbours_file, neighbours_txt_file, max_error);
834 
836  {
837  oomph_info << "\n \n Failed self_test() for QuadTree: Max. error "
838  << max_error << std::endl
839  << std::endl;
840  return 1;
841  }
842  else
843  {
844  oomph_info << "\n \n Passed self_test() for QuadTree: Max. error "
845  << max_error << std::endl
846  << std::endl;
847  return 0;
848  }
849  }
static void doc_neighbours(Vector< Tree * > forest_nodes_pt, std::ofstream &neighbours_file, std::ofstream &neighbours_txt_file, double &max_error)
Definition: quadtree.cc:1402
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::QuadTree::setup_static_data ( )
static

Setup the static data, rotation and reflection schemes, etc.

Setup the static data stored in the QuadTree – this needs to be called before QuadTrees can be used. Automatically called by RefineableQuadMesh constructor.

121  {
122  using namespace QuadTreeNames;
123 
124 
125 #ifdef PARANOID
127  {
128  std::ostringstream error_stream;
129  error_stream << "Inconsistent enumeration! \n Tree::OMEGA="
130  << Tree::OMEGA << "\nQuadTree::OMEGA=" << QuadTree::OMEGA
131  << std::endl;
132  throw OomphLibError(
133  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
134  }
135 #endif
136 
137 
138  // Set flag to indicate that static data has been setup
140 
141  // Tecplot Colours for neighbours in various directions
142  Colour.resize(27);
143  Colour[SW] = "YELLOW";
144  Colour[SE] = "YELLOW";
145  Colour[NW] = "YELLOW";
146  Colour[NE] = "YELLOW";
147  Colour[E] = "CYAN";
148  Colour[W] = "RED";
149  Colour[N] = "GREEN";
150  Colour[S] = "BLUE";
151  Colour[OMEGA] = "YELLOW";
152 
153  // S_base(i,direction): Initial value for coordinate s[i] on the
154  // edge indicated by direction (S/E/N/W)
155  //
156  // S_step(i,direction) Increments for coordinate s[i] when progressing
157  // along the edge indicated by direction (S/E/N/W)
158  S_base.resize(2, 27);
159  S_step.resize(2, 27);
160 
161  S_base(0, N) = -1.0;
162  S_base(1, N) = 1.0;
163  S_step(0, N) = 2.0;
164  S_step(1, N) = 0.0;
165 
166  S_base(0, S) = -1.0;
167  S_base(1, S) = -1.0;
168  S_step(0, S) = 2.0;
169  S_step(1, S) = 0.0;
170 
171  S_base(0, W) = -1.0;
172  S_base(1, W) = -1.0;
173  S_step(0, W) = 0.0;
174  S_step(1, W) = 2.0;
175 
176  S_base(0, E) = 1.0;
177  S_base(1, E) = -1.0;
178  S_step(0, E) = 0.0;
179  S_step(1, E) = 2.0;
180 
181  // Translate (enumerated) directions into strings
182  Direct_string.resize(27);
183 
184  Direct_string[SW] = "SW";
185  Direct_string[NW] = "NW";
186  Direct_string[SE] = "SE";
187  Direct_string[NE] = "NE";
188 
189  Direct_string[S] = "S";
190  Direct_string[N] = "N";
191  Direct_string[E] = "E";
192  Direct_string[W] = "W";
193  Direct_string[OMEGA] = "OMEGA";
194 
195  // Build direction/quadrant adjacency scheme
196  // Is_adjacent(i_vertex_or_edge,j_quadrant):
197  // Is edge/vertex adjacent to quadrant?
198  Is_adjacent.resize(27, 27);
199 
200  Is_adjacent(N, NW) = true;
201  Is_adjacent(E, NW) = false;
202  Is_adjacent(S, NW) = false;
203  Is_adjacent(W, NW) = true;
204  Is_adjacent(NW, NW) = true;
205  Is_adjacent(NE, NW) = false;
206  Is_adjacent(SW, NW) = false;
207  Is_adjacent(SE, NW) = false;
208 
209  Is_adjacent(N, NE) = true;
210  Is_adjacent(E, NE) = true;
211  Is_adjacent(S, NE) = false;
212  Is_adjacent(W, NE) = false;
213  Is_adjacent(NW, NE) = false;
214  Is_adjacent(NE, NE) = true;
215  Is_adjacent(SW, NE) = false;
216  Is_adjacent(SE, NE) = false;
217 
218  Is_adjacent(N, SW) = false;
219  Is_adjacent(E, SW) = false;
220  Is_adjacent(S, SW) = true;
221  Is_adjacent(W, SW) = true;
222  Is_adjacent(NW, SW) = false;
223  Is_adjacent(NE, SW) = false;
224  Is_adjacent(SW, SW) = true;
225  Is_adjacent(SE, SW) = false;
226 
227 
228  Is_adjacent(N, SE) = false;
229  Is_adjacent(E, SE) = true;
230  Is_adjacent(S, SE) = true;
231  Is_adjacent(W, SE) = false;
232  Is_adjacent(NW, SE) = false;
233  Is_adjacent(NE, SE) = false;
234  Is_adjacent(SW, SE) = false;
235  Is_adjacent(SE, SE) = true;
236 
237  // Rotation scheme: If north becomes NorthIs then
238  // direction becomes Rotate(NorthIs,direction)
239  // Initialise to OMEGA
240  Rotate.resize(27, 27);
241 
242  Rotate(N, N) = N;
243  Rotate(N, E) = E;
244  Rotate(N, S) = S;
245  Rotate(N, W) = W;
246  Rotate(N, NW) = NW;
247  Rotate(N, NE) = NE;
248  Rotate(N, SE) = SE;
249  Rotate(N, SW) = SW;
250 
251  Rotate(W, N) = W;
252  Rotate(W, E) = N;
253  Rotate(W, S) = E;
254  Rotate(W, W) = S;
255  Rotate(W, NW) = SW;
256  Rotate(W, NE) = NW;
257  Rotate(W, SE) = NE;
258  Rotate(W, SW) = SE;
259 
260  Rotate(S, N) = S;
261  Rotate(S, E) = W;
262  Rotate(S, S) = N;
263  Rotate(S, W) = E;
264  Rotate(S, NW) = SE;
265  Rotate(S, NE) = SW;
266  Rotate(S, SE) = NW;
267  Rotate(S, SW) = NE;
268 
269  Rotate(E, N) = E;
270  Rotate(E, E) = S;
271  Rotate(E, S) = W;
272  Rotate(E, W) = N;
273  Rotate(E, NW) = NE;
274  Rotate(E, NE) = SE;
275  Rotate(E, SE) = SW;
276  Rotate(E, SW) = NW;
277 
278  // Angle betwen rotated coordinates:
279  // old_direction becomes new_direction then the angle between
280  // the axes is Rotate_angle(old_direction,new_direction)
281  Rotate_angle.resize(27, 27);
282 
283  Rotate_angle(N, N) = 0;
284  Rotate_angle(N, W) = 90;
285  Rotate_angle(N, S) = 180;
286  Rotate_angle(N, E) = 270;
287 
288  Rotate_angle(S, S) = 0;
289  Rotate_angle(S, E) = 90;
290  Rotate_angle(S, N) = 180;
291  Rotate_angle(S, W) = 270;
292 
293  Rotate_angle(W, W) = 0;
294  Rotate_angle(W, S) = 90;
295  Rotate_angle(W, E) = 180;
296  Rotate_angle(W, N) = 270;
297 
298  Rotate_angle(E, E) = 0;
299  Rotate_angle(E, N) = 90;
300  Rotate_angle(E, W) = 180;
301  Rotate_angle(E, S) = 270;
302 
303  // Reflection scheme:
304  // Reflect(direction,quadrant): Get mirror of quadrant in direction
305  Reflect.resize(27, 27);
306 
307  Reflect(N, NW) = SW;
308  Reflect(E, NW) = NE;
309  Reflect(S, NW) = SW;
310  Reflect(W, NW) = NE;
311  Reflect(NW, NW) = SE;
312  Reflect(NE, NW) = SE;
313  Reflect(SW, NW) = SE;
314  Reflect(SE, NW) = SE;
315 
316  Reflect(N, NE) = SE;
317  Reflect(E, NE) = NW;
318  Reflect(S, NE) = SE;
319  Reflect(W, NE) = NW;
320  Reflect(NW, NE) = SW;
321  Reflect(NE, NE) = SW;
322  Reflect(SW, NE) = SW;
323  Reflect(SE, NE) = SW;
324 
325  Reflect(N, SW) = NW;
326  Reflect(E, SW) = SE;
327  Reflect(S, SW) = NW;
328  Reflect(W, SW) = SE;
329  Reflect(NW, SW) = NE;
330  Reflect(NE, SW) = NE;
331  Reflect(SW, SW) = NE;
332  Reflect(SE, SW) = NE;
333 
334  Reflect(N, SE) = NE;
335  Reflect(E, SE) = SW;
336  Reflect(S, SE) = NE;
337  Reflect(W, SE) = SW;
338  Reflect(NW, SE) = NW;
339  Reflect(NE, SE) = NW;
340  Reflect(SW, SE) = NW;
341  Reflect(SE, SE) = NW;
342 
343  // S_direct(direction,son_quadrant): The lower left corner of
344  // my son_quadrant has an offset of h/2 S_direct(direction,son_quadrant)
345  // in the direction. [Look in the positive direction along the
346  // edge 'direction' and measure the offset of the lower left corner
347  // of the son quadrant in this direction]
348  S_direct.resize(27, 27);
349 
350  S_direct(W, NW) = 1;
351  S_direct(E, NW) = 1;
352  S_direct(N, NW) = 0;
353  S_direct(S, NW) = 0;
354 
355  S_direct(W, NE) = 1;
356  S_direct(E, NE) = 1;
357  S_direct(N, NE) = 1;
358  S_direct(S, NE) = 1;
359 
360  S_direct(W, SW) = 0;
361  S_direct(E, SW) = 0;
362  S_direct(N, SW) = 0;
363  S_direct(S, SW) = 0;
364 
365  S_direct(W, SE) = 0;
366  S_direct(E, SE) = 0;
367  S_direct(N, SE) = 1;
368  S_direct(S, SE) = 1;
369 
370  // Get opposite edge, e.g. Reflect_edge(N)=S
371  Reflect_edge.resize(27);
372 
373  Reflect_edge[N] = S;
374  Reflect_edge[S] = N;
375  Reflect_edge[E] = W;
376  Reflect_edge[W] = E;
377  }
void resize(const unsigned long &n)
Definition: matrices.h:498
static bool Static_data_has_been_setup
Bool indicating that static member data has been setup.
Definition: quadtree.h:232
@ SE
Definition: quadtree.h:57
@ NW
Definition: quadtree.h:58
@ NE
Definition: quadtree.h:59
@ SW
Definition: quadtree.h:56

References Colour, Direct_string, Global_Physical_Variables::E, Is_adjacent, N, oomph::QuadTreeNames::NE, oomph::QuadTreeNames::NW, oomph::Tree::OMEGA, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, Reflect, Reflect_edge, oomph::DenseMatrix< T >::resize(), Rotate, Rotate_angle, oomph::QuadTreeNames::S, S_base, S_direct, S_step, oomph::QuadTreeNames::SE, Static_data_has_been_setup, oomph::QuadTreeNames::SW, and oomph::QuadTreeNames::W.

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

◆ stick_neighbouring_leaves_into_vector()

void oomph::QuadTree::stick_neighbouring_leaves_into_vector ( Vector< const QuadTree * > &  tree_neighbouring_nodes,
Vector< Vector< double >> &  tree_neighbouring_s_lo,
Vector< Vector< double >> &  tree_neighbouring_s_hi,
Vector< int > &  tree_neighbouring_diff_level,
const QuadTree my_neigh_pt,
const int direction 
) const

Traverse Tree: Preorder traverse and stick pointers to neighbouring leaf nodes (only) into Vector

758  {
759  // If the tree has sons
760  unsigned numsons = Son_pt.size();
761  if (numsons > 0)
762  {
763  // Now do the sons (if they exist)
764  for (unsigned i = 0; i < numsons; i++)
765  {
766  dynamic_cast<QuadTree*>(Son_pt[i])
767  ->stick_neighbouring_leaves_into_vector(tree_neighbouring_nodes,
768  tree_neighbouring_s_lo,
769  tree_neighbouring_s_hi,
770  tree_neighbouring_diff_level,
771  my_neigh_pt,
772  direction);
773  }
774  }
775  else
776  {
777  // Required data for neighbour-finding routine
778  Vector<unsigned> translate_s(2);
779  Vector<double> s_lo(2), s_hi(2);
780  int edge, diff_level;
781  bool in_neighbouring_tree;
782  QuadTree* neigh_pt;
783 
784  // Get neighbouring tree
785  neigh_pt = gteq_edge_neighbour(direction,
786  translate_s,
787  s_lo,
788  s_hi,
789  edge,
790  diff_level,
791  in_neighbouring_tree);
792 
793  // Check if the neighbour is the same as the tree passed in
794  // (i.e. Am I a neighbour of the master element's tree?)
795  if (neigh_pt == my_neigh_pt)
796  {
797  // Add the element and the diff_level to passed vectors
798  tree_neighbouring_nodes.push_back(this);
799  tree_neighbouring_s_lo.push_back(s_lo);
800  tree_neighbouring_s_hi.push_back(s_hi);
801  tree_neighbouring_diff_level.push_back(diff_level);
802  }
803  }
804  }
void stick_neighbouring_leaves_into_vector(Vector< const QuadTree * > &tree_neighbouring_nodes, Vector< Vector< double >> &tree_neighbouring_s_lo, Vector< Vector< double >> &tree_neighbouring_s_hi, Vector< int > &tree_neighbouring_diff_level, const QuadTree *my_neigh_pt, const int &direction) const
Definition: quadtree.cc:751
Vector< Tree * > Son_pt
Vector of pointers to the sons of the Tree.
Definition: tree.h:299

References gteq_edge_neighbour(), i, and oomph::Tree::Son_pt.

Member Data Documentation

◆ Colour

Vector< std::string > oomph::QuadTree::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::QuadTree::Direct_string
static

Translate (enumerated) directions into strings.

Translate (enumerated) directions into strings (static data)

Referenced by oomph::QuadTreeRoot::north_equivalent(), and setup_static_data().

◆ Is_adjacent

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

Array of direction/quadrant adjacency scheme: Is_adjacent(i_vertex_or_edge,j_quadrant): Is edge/vertex adjacent to quadrant?

Array of direction/quadrant adjacency scheme: Is_adjacent(i_vertex_or_edge,j_quadrant): Is edge/vertex adjacent to quadrant? (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ Reflect

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

Reflection scheme: Reflect(direction,quadrant): Get mirror of quadrant in specified direction. E.g. Reflect(S,NE)=SE

Reflection scheme: Reflect(direction,quadrant): Get mirror of quadrant in specified direction. E.g. Reflect(S,NE)=SE (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ Reflect_edge

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

Get opposite edge, e.g. Reflect_edge[N]=S.

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

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ Rotate

DenseMatrix< int > oomph::QuadTree::Rotate
staticprivate

Rotate coordinates: If North becomes NorthIs then direction becomes Rotate(NorthIs,direction). E.g. Rotate(E,NW)=NE;

Rotate coordinates: If north becomes NorthIs then direction becomes Rotate(NorthIs,direction). E.g. Rotate(E,NW)=NE; (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ Rotate_angle

DenseMatrix< int > oomph::QuadTree::Rotate_angle
staticprivate

Angle betwen rotated coordinates: If old_direction becomes new_direction then the angle between the axes (in anti-clockwise direction is Rotate_angle(old_direction,new_direction); E.g. Rotate_angle(E,N)=90;

Angle betwen rotated coordinates: If old_direction becomes new_direction then the angle between the axes (in anti-clockwise direction is Rotate_angle(old_direction,new_direction); E.g. Rotate_angle(E,N)=90; (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ S_base

DenseMatrix< double > oomph::QuadTree::S_base
staticprivate

S_base(i,direction): Initial value for coordinate s[i] on the edge indicated by direction (S/E/N/W)

S_base(i,direction): Initial value for coordinate s[i] on the edge indicated by direction (S/E/N/W) (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ S_direct

DenseMatrix< int > oomph::QuadTree::S_direct
staticprivate

S_direct(direction,son_quadrant): The lower left corner of son_quadrant has an offset of h/2 S_direct(direction,son_quadrant) in the specified direction. E.g. S_direct(S,NE)=1 and S_direct(S,NW)=0

S_direct(direction,son_quadrant): The lower left corner of son_quadrant has an offset of h/2 S_direct(direction,son_quadrant) in the specified direction. E.g. S_direct(S,NE)=1 and S_direct(S,NW)=0 (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ S_step

DenseMatrix< double > oomph::QuadTree::S_step
staticprivate

S_step(i,direction) Increments for coordinate s[i] when progressing along the edge indicated by direction (S/E/N/W); Left/lower vertex: S_base; Right/upper vertex: S_base + S_step

S_step(i,direction) Increments for coordinate s[i] when progressing along the edge indicated by direction (S/E/N/W); Left/lower vertex: S_base; Right/upper vertex: S_base + S_step (static data)

Referenced by gteq_edge_neighbour(), and setup_static_data().

◆ Static_data_has_been_setup

bool oomph::QuadTree::Static_data_has_been_setup = false
staticprotected

Bool indicating that static member data has been setup.

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


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