31 #include <oomph-lib-config.h> 
  122     using namespace QuadTreeNames;
 
  128       std::ostringstream error_stream;
 
  129       error_stream << 
"Inconsistent enumeration!  \n    Tree::OMEGA=" 
  133         error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
 
  419                                           bool& in_neighbouring_tree)
 const 
  421     using namespace QuadTreeNames;
 
  424     if ((direction != 
S) && (direction != 
E) && (direction != 
N) &&
 
  427       std::ostringstream error_stream;
 
  428       error_stream << 
"Direction " << direction << 
" is not N, S, E, W" 
  432         error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
 
  438     in_neighbouring_tree = 
false;
 
  442     int max_level = 
Level;
 
  457                                               in_neighbouring_tree,
 
  470       int new_dir = direction;
 
  506             if (s_lo[1] != s_hi[1])
 
  515             if (s_lo[0] != s_hi[0])
 
  522             std::ostringstream error_stream;
 
  523             error_stream << 
"Direction " << direction << 
" is not N, S, E, W" 
  527                                 OOMPH_CURRENT_FUNCTION,
 
  528                                 OOMPH_EXCEPTION_LOCATION);
 
  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];
 
  551       if (((edge == 
N) || (edge == 
S)) &&
 
  555         s_lo_new[0] = -s_lo[0];
 
  556         s_hi_new[0] = -s_hi[0];
 
  558       if (((edge == 
E) || (edge == 
W)) &&
 
  562         s_lo_new[1] = -s_lo[1];
 
  563         s_hi_new[1] = -s_hi[1];
 
  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];
 
  602     const int& direction,
 
  605     bool& in_neighbouring_tree,
 
  609     using namespace QuadTreeNames;
 
  612     if ((direction != 
S) && (direction != 
E) && (direction != 
N) &&
 
  615       std::ostringstream error_stream;
 
  616       error_stream << 
"Direction " << direction << 
" is not N, S, E, W" 
  620         error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
 
  648           in_neighbouring_tree,
 
  680         if ((next_el_pt->
Son_pt.size() == 0) ||
 
  681             (next_el_pt->
Level > max_level - 1))
 
  683           return_el_pt = next_el_pt;
 
  697           if (orig_root_pt != next_el_pt->
Root_pt)
 
  702             son_quadrant = 
Rotate(my_north, son_quadrant);
 
  733         in_neighbouring_tree = 
true;
 
  757     const int& direction)
 const 
  760     unsigned numsons = 
Son_pt.size();
 
  764       for (
unsigned i = 0; 
i < numsons; 
i++)
 
  768                                                   tree_neighbouring_s_lo,
 
  769                                                   tree_neighbouring_s_hi,
 
  770                                                   tree_neighbouring_diff_level,
 
  780       int edge, diff_level;
 
  781       bool in_neighbouring_tree;
 
  791                                      in_neighbouring_tree);
 
  795       if (neigh_pt == my_neigh_pt)
 
  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);
 
  821     unsigned long num_nodes = all_nodes_pt.size();
 
  822     for (
unsigned long i = 0; 
i < num_nodes; 
i++)
 
  824       all_nodes_pt[
i]->object_pt()->set_number(++count);
 
  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);
 
  837       oomph_info << 
"\n \n Failed self_test() for QuadTree: Max. error " 
  838                  << max_error << std::endl
 
  844       oomph_info << 
"\n \n Passed self_test() for QuadTree: Max. error " 
  845                  << max_error << std::endl
 
  871     if (trees_pt.size() == 0)
 
  876     using namespace QuadTreeNames;
 
  893     using namespace QuadTreeNames;
 
  895     unsigned numtrees = 
ntree();
 
  899       n = 
Trees_pt[0]->object_pt()->nnode_1d();
 
  904         "Trying to setup the neighbour scheme for an empty forest\n",
 
  905         OOMPH_CURRENT_FUNCTION,
 
  906         OOMPH_EXCEPTION_LOCATION);
 
  910     unsigned n_vertex_node = 4;
 
  914     std::map<Node*, std::set<unsigned>> tree_assoc_with_vertex_node;
 
  917     for (
unsigned i = 0; 
i < numtrees; 
i++)
 
  920       for (
unsigned j = 0; j < n_vertex_node; j++)
 
  924         tree_assoc_with_vertex_node[nod_pt].insert(
i);
 
  934     for (std::map<
Node*, std::set<unsigned>>::iterator it =
 
  935            tree_assoc_with_vertex_node.begin();
 
  936          it != tree_assoc_with_vertex_node.end();
 
  940       for (std::set<unsigned>::iterator it_el1 = it->second.begin();
 
  941            it_el1 != it->second.end();
 
  944         unsigned i = (*it_el1);
 
  945         for (std::set<unsigned>::iterator it_el2 = it->second.begin();
 
  946              it_el2 != it->second.end();
 
  949           unsigned j = (*it_el2);
 
  953             potentially_neighb_tree[
i].insert(j);
 
  961     for (
unsigned i = 0; 
i < numtrees; 
i++)
 
  964       for (std::set<unsigned>::iterator it = potentially_neighb_tree[
i].begin();
 
  965            it != potentially_neighb_tree[
i].end();
 
  971         bool is_N_neighbour =
 
  972           ((
Trees_pt[j]->object_pt()->get_node_number(
 
  973               Trees_pt[
i]->object_pt()->node_pt(n * (n - 1))) != -1) &&
 
  974            (
Trees_pt[j]->object_pt()->get_node_number(
 
  975               Trees_pt[
i]->object_pt()->node_pt(n * n - 1)) != -1));
 
  979         bool is_S_neighbour =
 
  980           ((
Trees_pt[j]->object_pt()->get_node_number(
 
  981               Trees_pt[
i]->object_pt()->node_pt(0)) != -1) &&
 
  982            (
Trees_pt[j]->object_pt()->get_node_number(
 
  983               Trees_pt[
i]->object_pt()->node_pt(n - 1)) != -1));
 
  987         bool is_E_neighbour =
 
  988           ((
Trees_pt[j]->object_pt()->get_node_number(
 
  989               Trees_pt[
i]->object_pt()->node_pt(n - 1)) != -1) &&
 
  990            (
Trees_pt[j]->object_pt()->get_node_number(
 
  991               Trees_pt[
i]->object_pt()->node_pt(n * n - 1)) != -1));
 
  994         bool is_W_neighbour =
 
  995           ((
Trees_pt[j]->object_pt()->get_node_number(
 
  996               Trees_pt[
i]->object_pt()->node_pt(0)) != -1) &&
 
  997            (
Trees_pt[j]->object_pt()->get_node_number(
 
  998               Trees_pt[
i]->object_pt()->node_pt(n * (n - 1))) != -1));
 
 1013       for (
unsigned i = 0; 
i < numtrees; 
i++)
 
 1016         for (
unsigned j = 0; j < numtrees; j++)
 
 1021             bool is_N_neighbour =
 
 1022               ((
Trees_pt[j]->object_pt()->get_node_number(
 
 1023                   Trees_pt[
i]->object_pt()->node_pt(n * (n - 1))) != -1) &&
 
 1024                (
Trees_pt[j]->object_pt()->get_node_number(
 
 1025                   Trees_pt[
i]->object_pt()->node_pt(n * n - 1)) != -1));
 
 1029             bool is_S_neighbour =
 
 1030               ((
Trees_pt[j]->object_pt()->get_node_number(
 
 1031                   Trees_pt[
i]->object_pt()->node_pt(0)) != -1) &&
 
 1032                (
Trees_pt[j]->object_pt()->get_node_number(
 
 1033                   Trees_pt[
i]->object_pt()->node_pt(n - 1)) != -1));
 
 1037             bool is_E_neighbour =
 
 1038               ((
Trees_pt[j]->object_pt()->get_node_number(
 
 1039                   Trees_pt[
i]->object_pt()->node_pt(n - 1)) != -1) &&
 
 1040                (
Trees_pt[j]->object_pt()->get_node_number(
 
 1041                   Trees_pt[
i]->object_pt()->node_pt(n * n - 1)) != -1));
 
 1044             bool is_W_neighbour =
 
 1045               ((
Trees_pt[j]->object_pt()->get_node_number(
 
 1046                   Trees_pt[
i]->object_pt()->node_pt(0)) != -1) &&
 
 1047                (
Trees_pt[j]->object_pt()->get_node_number(
 
 1048                   Trees_pt[
i]->object_pt()->node_pt(n * (n - 1))) != -1));
 
 1069     using namespace QuadTreeNames;
 
 1071     unsigned numtrees = 
ntree();
 
 1073     for (
unsigned i = 0; 
i < numtrees; 
i++)
 
 1104             std::ostringstream error_stream;
 
 1107               << 
"'s Northern neighbour has no neighbour pointer to Tree " << 
i 
 1111                                 OOMPH_CURRENT_FUNCTION,
 
 1112                                 OOMPH_EXCEPTION_LOCATION);
 
 1145             std::ostringstream error_stream;
 
 1148               << 
"'s Eastern neighbour has no neighbour pointer to Tree " << 
i 
 1152                                 OOMPH_CURRENT_FUNCTION,
 
 1153                                 OOMPH_EXCEPTION_LOCATION);
 
 1186             std::ostringstream error_stream;
 
 1189               << 
"'s Southern neighbour has no neighbour pointer to Tree " << 
i 
 1193                                 OOMPH_CURRENT_FUNCTION,
 
 1194                                 OOMPH_EXCEPTION_LOCATION);
 
 1227             std::ostringstream error_stream;
 
 1230               << 
"'s Western neighbour has no neighbour pointer to Tree " << 
i 
 1234                                 OOMPH_CURRENT_FUNCTION,
 
 1235                                 OOMPH_EXCEPTION_LOCATION);
 
 1252     std::ofstream neigh_file;
 
 1253     std::ofstream neigh_txt_file;
 
 1258       std::ostringstream fullname;
 
 1259       fullname << doc_info.
directory() << 
"/neighbours" << doc_info.
number()
 
 1261       oomph_info << 
"opened " << fullname.str() << 
" to doc neighbours" 
 1263       neigh_file.open(fullname.str().c_str());
 
 1265       fullname << doc_info.
directory() << 
"/neighbours" << doc_info.
number()
 
 1267       oomph_info << 
"opened " << fullname.str() << 
" to doc neighbours" 
 1269       neigh_txt_file.open(fullname.str().c_str());
 
 1273     double max_error = 0.0;
 
 1275       all_tree_nodes_pt, neigh_file, neigh_txt_file, max_error);
 
 1280       std::ostringstream error_stream;
 
 1281       error_stream << 
"Max. error in quadtree neighbour finding: " << max_error
 
 1282                    << 
" is too big" << std::endl;
 
 1284         << 
"i.e. bigger than Tree::max_neighbour_finding_tolerance()=" 
 1291         neigh_txt_file.close();
 
 1295         error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
 
 1299       oomph_info << 
"Max. error in quadtree neighbour finding: " << max_error
 
 1300                  << 
" is OK" << std::endl;
 
 1302         << 
"i.e. less than QuadTree::max_neighbour_finding_tolerance()=" 
 1310       neigh_txt_file.close();
 
 1322     for (
unsigned i = 0; 
i < 4; 
i++)
 
 1324       output_stream.push_back(
new std::ofstream);
 
 1330       std::ostringstream fullname;
 
 1331       fullname << doc_info.
directory() << 
"/hang_nodes_s" << doc_info.
number()
 
 1333       output_stream[0]->open(fullname.str().c_str());
 
 1335       fullname << doc_info.
directory() << 
"/hang_nodes_n" << doc_info.
number()
 
 1337       output_stream[1]->open(fullname.str().c_str());
 
 1339       fullname << doc_info.
directory() << 
"/hang_nodes_w" << doc_info.
number()
 
 1341       output_stream[2]->open(fullname.str().c_str());
 
 1343       fullname << doc_info.
directory() << 
"/hang_nodes_e" << doc_info.
number()
 
 1345       output_stream[3]->open(fullname.str().c_str());
 
 1364     unsigned long num_nodes = all_forest_nodes_pt.size();
 
 1365     for (
unsigned long i = 0; 
i < num_nodes; 
i++)
 
 1367       all_forest_nodes_pt[
i]->object_pt()->set_number(++count);
 
 1372     double max_error = 0.0;
 
 1373     std::ofstream neighbours_file;
 
 1374     std::ofstream neighbours_txt_file;
 
 1376       all_forest_nodes_pt, neighbours_file, neighbours_txt_file, max_error);
 
 1379       oomph_info << 
"\n \n Failed self_test() for QuadTree: Max. error " 
 1380                  << max_error << std::endl
 
 1386       oomph_info << 
"\n \n Passed self_test() for QuadTree: Max. error " 
 1387                  << max_error << std::endl
 
 1403                                 std::ofstream& neighbours_file,
 
 1404                                 std::ofstream& neighbours_txt_file,
 
 1407     using namespace QuadTreeNames;
 
 1411     bool in_neighbouring_tree;
 
 1431     unsigned long num_nodes = forest_nodes_pt.size();
 
 1432     for (
unsigned long i = 0; 
i < num_nodes; 
i++)
 
 1435       forest_nodes_pt[
i]->object_pt()->set_number(
i);
 
 1440     for (
unsigned long i = 0; 
i < num_nodes; 
i++)
 
 1449         if (neighbours_file.is_open())
 
 1452             ->output_corners(neighbours_file, 
"BLACK");
 
 1457         for (
int direction = 
N; direction <= 
W; direction++)
 
 1471                                        in_neighbouring_tree);
 
 1477             if (neighbours_txt_file.is_open())
 
 1480                 << Direct_string[direction] << 
" neighbour of " 
 1483                 << diff_level << 
" s_diff " << s_diff
 
 1484                 << 
" inside neighbour the edge is " << Direct_string[edge]
 
 1490             if (neighbours_file.is_open())
 
 1493                 ->output_corners(neighbours_file, Colour[direction]);
 
 1501               if (neighbours_file.is_open())
 
 1503                 neighbours_file << 
"ZONE I=2 \n";
 
 1516               s[0] = S_base(0, direction);
 
 1517               s[1] = S_base(1, direction);
 
 1524               bool is_periodic = 
false;
 
 1525               if (in_neighbouring_tree)
 
 1534               if (is_periodic == 
false)
 
 1536                 for (
int i = 0; 
i < 2; 
i++)
 
 1538                   error += pow(x_small[
i] - x_large[
i], 2);
 
 1543               error = sqrt(error);
 
 1544               if (neighbours_txt_file.is_open())
 
 1546                 neighbours_txt_file << 
"Error (1) " << error << std::endl;
 
 1549               if (std::fabs(error) > max_error)
 
 1551                 max_error = std::fabs(error);
 
 1554               if (neighbours_file.is_open())
 
 1556                 neighbours_file << x_large[0] << 
" " << x_large[1] << 
"  0 \n";
 
 1568               s[0] = S_base(0, direction) + S_step(0, direction);
 
 1569               s[1] = S_base(1, direction) + S_step(1, direction);
 
 1574               if (is_periodic == 
false)
 
 1576                 for (
int i = 0; 
i < 2; 
i++)
 
 1578                   error += pow(x_small[
i] - x_large[
i], 2);
 
 1582               error = sqrt(error);
 
 1586               if (neighbours_txt_file.is_open())
 
 1588                 neighbours_txt_file << 
"Error (2) " << error << std::endl;
 
 1591               if (std::fabs(error) > max_error)
 
 1593                 max_error = std::fabs(error);
 
 1596               if (neighbours_file.is_open())
 
 1598                 neighbours_file << x_large[0] << 
" " << x_large[1] << 
"  0 \n";
 
 1618             if (neighbours_file.is_open())
 
 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";
 
void resize(const unsigned long &n)
Resize to a square nxn matrix; any values already present will be transfered.
Information for documentation of results: Directory and file number to enable output in the form RESL...
bool is_doc_enabled() const
Are we documenting?
std::string directory() const
Output directory.
unsigned & number()
Number used (e.g.) for labeling output files.
void get_x(const Vector< double > &s, Vector< double > &x) const
Global coordinates as function of local coordinates. Either via FE representation or via macro-elemen...
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
An OomphLibError object which should be thrown when an run-time error is encountered....
Base class for all quad elements.
QuadTreeRoot * quadtree_pt(const unsigned &i)
Return pointer to i-th root quadtree in this forest. (Performs a dynamic cast from the TreeRoot to a ...
QuadTreeForest()
Default constructor (empty and broken)
QuadTreeRoot * quad_neigh_pt(const unsigned &i, const int &direction)
Given the number i of the root quadtree in this forest, return pointer to its neighbour in the specif...
void check_all_neighbours(DocInfo &doc_info)
Document and check all the neighbours of all the nodes in the forest. DocInfo object specifies the ou...
void find_neighbours()
Construct the neighbour lookup scheme.
unsigned self_test()
Self-test: Check all neighbours. Return success (0) if the max. distance between corresponding points...
void construct_north_equivalents()
Construct the rotation schemes.
void open_hanging_node_files(DocInfo &doc_info, Vector< std::ofstream * > &output_stream)
Open output files that will store any hanging nodes in the forest and return a vector of the streams.
QuadTreeRoot is a QuadTree that forms the root of a (recursive) quadtree. The "root node" is special ...
int & north_equivalent(const int &neighbour)
Return north equivalent of the neighbours in specified direction: When viewed from the current quadtr...
int direction_of_neighbour(QuadTreeRoot *quadtree_root_pt)
If quadtree_root_pt is a neighbour, return the direction [N/S/E/W] in which it is found,...
QuadTree class: Recursively defined, generalised quadtree.
static Vector< std::string > Direct_string
Translate (enumerated) directions into strings.
static void doc_neighbours(Vector< Tree * > forest_nodes_pt, std::ofstream &neighbours_file, std::ofstream &neighbours_txt_file, double &max_error)
Doc/check all neighbours of quadtree (nodes) contained in the Vector forest_node_pt....
static DenseMatrix< double > S_step
S_step(i,direction) Increments for coordinate s[i] when progressing along the edge indicated by direc...
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
Traverse Tree: Preorder traverse and stick pointers to neighbouring leaf nodes (only) into Vector.
static Vector< int > Reflect_edge
Get opposite edge, e.g. Reflect_edge[N]=S.
static DenseMatrix< int > Reflect
Reflection scheme: Reflect(direction,quadrant): Get mirror of quadrant in specified direction....
static DenseMatrix< int > Rotate
Rotate coordinates: If North becomes NorthIs then direction becomes Rotate(NorthIs,...
static void setup_static_data()
Setup the static data, rotation and reflection schemes, etc.
static DenseMatrix< double > S_base
S_base(i,direction): Initial value for coordinate s[i] on the edge indicated by direction (S/E/N/W)
static DenseMatrix< int > S_direct
S_direct(direction,son_quadrant): The lower left corner of son_quadrant has an offset of h/2 S_direct...
unsigned self_test()
Self-test: Check all neighbours. Return success (0) if the max. distance between corresponding points...
static Vector< std::string > Colour
Colours for neighbours in various directions.
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 reg...
static DenseMatrix< bool > Is_adjacent
Array of direction/quadrant adjacency scheme: Is_adjacent(i_vertex_or_edge,j_quadrant): Is edge/verte...
static bool Static_data_has_been_setup
Bool indicating that static member data has been setup.
static DenseMatrix< int > Rotate_angle
Angle betwen rotated coordinates: If old_direction becomes new_direction then the angle between the a...
long number() const
Element number (for debugging/plotting)
virtual bool nodes_built()
Return true if all the nodes have been built, false if not.
Refineable version of QElement<2,NNODE_1D>.
A TreeForest consists of a collection of TreeRoots. Each member tree can have neighbours in various e...
void stick_all_tree_nodes_into_vector(Vector< Tree * > &all_forest_nodes)
Traverse forest and stick pointers to all "nodes" into Vector.
unsigned ntree()
Number of trees in forest.
Vector< TreeRoot * > Trees_pt
Vector containing the pointers to the trees.
bool is_neighbour_periodic(const int &direction)
Return whether the neighbour in the particular direction is periodic.
TreeRoot *& neighbour_pt(const int &direction)
Return the pointer to the neighbouring TreeRoots in specified direction. Returns NULL if there's no n...
Tree * Father_pt
Pointer to the Father of the Tree.
void stick_all_tree_nodes_into_vector(Vector< Tree * > &)
Traverse and stick pointers to all "nodes" into Vector.
RefineableElement * object_pt() const
Return the pointer to the object (RefineableElement) represented by the tree.
TreeRoot * Root_pt
Pointer to the root of the tree.
int Son_type
Son type (e.g. SW/SE/NW/NE in a quadtree)
int Level
Level of the Tree (level 0 = root)
static const int OMEGA
Default value for an unassigned neighbour.
Vector< Tree * > Son_pt
Vector of pointers to the sons of the Tree.
TreeRoot *& root_pt()
Return pointer to root of the tree.
static double Max_neighbour_finding_tolerance
Max. allowed discrepancy in neighbour finding routine (distance between points when identified from t...
static double & max_neighbour_finding_tolerance()
Max. allowed discrepancy in neighbour finding routine (distance between points when identified from t...
long QuadTreeForest_build
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...