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...