35 #include <oomph-lib-config.h> 129 using namespace QuadTreeNames;
135 std::ostringstream error_stream;
137 <<
"Inconsistent enumeration! \n Tree::OMEGA=" <<
Tree::OMEGA 141 OOMPH_CURRENT_FUNCTION,
142 OOMPH_EXCEPTION_LOCATION);
425 int& edge,
int& diff_level,
426 bool &in_neighbouring_tree)
const 428 using namespace QuadTreeNames;
431 if ((direction!=
S)&&(direction!=
E)&&(direction!=
N)&&(direction!=
W))
433 std::ostringstream error_stream;
434 error_stream <<
"Direction " << direction
435 <<
" is not N, S, E, W" << std::endl;
438 OOMPH_CURRENT_FUNCTION,
439 OOMPH_EXCEPTION_LOCATION);
445 in_neighbouring_tree=
false;
463 in_neighbouring_tree,
476 int new_dir=direction;
510 if(s_lo[1] != s_hi[1]) {swap =
true;}
516 if(s_lo[0] != s_hi[0]) {swap =
true;}
520 std::ostringstream error_stream;
521 error_stream <<
"Direction " << direction
522 <<
" is not N, S, E, W" << std::endl;
525 OOMPH_CURRENT_FUNCTION,
526 OOMPH_EXCEPTION_LOCATION);
530 if(swap) {translate_s[0] = 1; translate_s[1] = 0;}
532 else {translate_s[0] = 0; translate_s[1] = 1;}
541 if ( ( (edge==
N)||(edge==
S) ) &&
545 s_lo_new[0]=-s_lo[0];
546 s_hi_new[0]=-s_hi[0];
548 if ( ( (edge==
E)||(edge==
W) ) &&
552 s_lo_new[1]=-s_lo[1];
553 s_hi_new[1]=-s_hi[1];
593 const int& direction,
596 bool &in_neighbouring_tree,
600 using namespace QuadTreeNames;
603 if ((direction!=
S)&&(direction!=
E)&&(direction!=
N)&&(direction!=
W))
605 std::ostringstream error_stream;
606 error_stream <<
"Direction " << direction
607 <<
" is not N, S, E, W" << std::endl;
610 OOMPH_CURRENT_FUNCTION,
611 OOMPH_EXCEPTION_LOCATION);
638 in_neighbouring_tree,
670 if ((next_el_pt->Son_pt.size()==0)||(next_el_pt->Level>max_level-1))
672 return_el_pt=next_el_pt;
686 if (orig_root_pt!=next_el_pt->
Root_pt)
691 son_quadrant=
Rotate(my_north,son_quadrant);
696 return_el_pt=
dynamic_cast<QuadTree*
>(next_el_pt->Son_pt[son_quadrant]);
721 in_neighbouring_tree=
true;
745 const int& direction)
const 748 unsigned numsons=
Son_pt.size();
752 for(
unsigned i=0;
i<numsons;
i++)
756 tree_neighbouring_s_lo,
757 tree_neighbouring_s_hi,
758 tree_neighbouring_diff_level,
768 int edge, diff_level;
769 bool in_neighbouring_tree;
774 diff_level, in_neighbouring_tree);
778 if(neigh_pt==my_neigh_pt)
781 tree_neighbouring_nodes.push_back(
this);
782 tree_neighbouring_s_lo.push_back(s_lo);
783 tree_neighbouring_s_hi.push_back(s_hi);
784 tree_neighbouring_diff_level.push_back(diff_level);
804 unsigned long num_nodes=all_nodes_pt.size();
805 for (
unsigned long i=0;
i<num_nodes;
i++)
807 all_nodes_pt[
i]->object_pt()->set_number(++count);
812 double max_error=0.0;
813 std::ofstream neighbours_file;
814 std::ofstream neighbours_txt_file;
816 neighbours_txt_file, max_error);
820 oomph_info <<
"\n \n Failed self_test() for QuadTree: Max. error " 821 << max_error << std::endl<< std::endl;
826 oomph_info <<
"\n \n Passed self_test() for QuadTree: Max. error " 827 << max_error << std::endl<< std::endl;
854 if (trees_pt.size()==0)
859 using namespace QuadTreeNames;
876 using namespace QuadTreeNames;
878 unsigned numtrees =
ntree();
882 n=
Trees_pt[0]->object_pt()->nnode_1d();
887 "Trying to setup the neighbour scheme for an empty forest\n",
888 OOMPH_CURRENT_FUNCTION,
889 OOMPH_EXCEPTION_LOCATION);
893 unsigned n_vertex_node=4;
897 std::map<Node*,std::set<unsigned> > tree_assoc_with_vertex_node;
900 for(
unsigned i=0;
i<numtrees;
i++)
903 for (
unsigned j=0;j<n_vertex_node;j++)
907 tree_assoc_with_vertex_node[nod_pt].insert(
i);
917 for (std::map<
Node*,std::set<unsigned> >::iterator it=
918 tree_assoc_with_vertex_node.begin();
919 it!=tree_assoc_with_vertex_node.end();it++)
922 for (std::set<unsigned>::iterator it_el1=it->second.begin();
923 it_el1!=it->second.end();it_el1++)
925 unsigned i=(*it_el1);
926 for (std::set<unsigned>::iterator it_el2=it->second.begin();
927 it_el2!=it->second.end();it_el2++)
929 unsigned j=(*it_el2);
933 potentially_neighb_tree[
i].insert(j);
941 for(
unsigned i=0;
i<numtrees;
i++)
944 for(std::set<unsigned>::iterator it=potentially_neighb_tree[
i].begin();
945 it!=potentially_neighb_tree[
i].end();it++)
951 ((
Trees_pt[j]->object_pt()->get_node_number(
952 Trees_pt[
i]->object_pt()->node_pt(n*(n-1)))!=-1) &&
953 (
Trees_pt[j]->object_pt()->get_node_number(
954 Trees_pt[
i]->object_pt()->node_pt(n*n-1))!=-1));
959 ((
Trees_pt[j]->object_pt()->get_node_number(
960 Trees_pt[
i]->object_pt()->node_pt(0))!=-1) &&
961 (
Trees_pt[j]->object_pt()->get_node_number(
962 Trees_pt[
i]->object_pt()->node_pt(n-1))!=-1));
967 ((
Trees_pt[j]->object_pt()->get_node_number(
968 Trees_pt[
i]->object_pt()->node_pt(n-1))!=-1) &&
969 (
Trees_pt[j]->object_pt()->get_node_number(
970 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(0))!=-1) &&
976 (
Trees_pt[j]->object_pt()->get_node_number(
977 Trees_pt[
i]->object_pt()->node_pt(n*(n-1)))!=-1));
994 for(
unsigned i=0;
i<numtrees;
i++)
997 for(
unsigned j=0;j<numtrees;j++)
1002 bool is_N_neighbour=
1003 ((
Trees_pt[j]->object_pt()->get_node_number(
1004 Trees_pt[
i]->object_pt()->node_pt(n*(n-1)))!=-1) &&
1005 (
Trees_pt[j]->object_pt()->get_node_number(
1006 Trees_pt[
i]->object_pt()->node_pt(n*n-1))!=-1));
1010 bool is_S_neighbour=
1011 ((
Trees_pt[j]->object_pt()->get_node_number(
1012 Trees_pt[
i]->object_pt()->node_pt(0))!=-1) &&
1013 (
Trees_pt[j]->object_pt()->get_node_number(
1014 Trees_pt[
i]->object_pt()->node_pt(n-1))!=-1));
1018 bool is_E_neighbour=
1019 ((
Trees_pt[j]->object_pt()->get_node_number(
1020 Trees_pt[
i]->object_pt()->node_pt(n-1))!=-1) &&
1021 (
Trees_pt[j]->object_pt()->get_node_number(
1022 Trees_pt[
i]->object_pt()->node_pt(n*n-1))!=-1));
1025 bool is_W_neighbour=
1026 ((
Trees_pt[j]->object_pt()->get_node_number(
1027 Trees_pt[
i]->object_pt()->node_pt(0))!=-1) &&
1028 (
Trees_pt[j]->object_pt()->get_node_number(
1029 Trees_pt[
i]->object_pt()->node_pt(n*(n-1)))!=-1));
1051 using namespace QuadTreeNames;
1053 unsigned numtrees =
ntree();
1055 for(
unsigned i=0;
i<numtrees;
i++)
1086 std::ostringstream error_stream;
1089 <<
"'s Northern neighbour has no neighbour pointer to Tree " <<
i 1093 OOMPH_CURRENT_FUNCTION,
1094 OOMPH_EXCEPTION_LOCATION);
1104 int direction = neigh_pt->direction_of_neighbour(
quadtree_pt(
i));
1127 std::ostringstream error_stream;
1130 <<
"'s Eastern neighbour has no neighbour pointer to Tree " <<
i 1134 OOMPH_CURRENT_FUNCTION,
1135 OOMPH_EXCEPTION_LOCATION);
1145 int direction = neigh_pt->direction_of_neighbour(
quadtree_pt(
i));
1168 std::ostringstream error_stream;
1171 <<
"'s Southern neighbour has no neighbour pointer to Tree " <<
i 1175 OOMPH_CURRENT_FUNCTION,
1176 OOMPH_EXCEPTION_LOCATION);
1186 int direction = neigh_pt->direction_of_neighbour(
quadtree_pt(
i));
1209 std::ostringstream error_stream;
1212 <<
"'s Western neighbour has no neighbour pointer to Tree " <<
i 1216 OOMPH_CURRENT_FUNCTION,
1217 OOMPH_EXCEPTION_LOCATION);
1234 std::ofstream neigh_file;
1235 std::ofstream neigh_txt_file;
1240 std::ostringstream fullname;
1241 fullname << doc_info.
directory() <<
"/neighbours" 1242 << doc_info.
number() <<
".dat";
1243 oomph_info <<
"opened " << fullname.str() <<
" to doc neighbours" 1245 neigh_file.open(fullname.str().c_str());
1247 fullname << doc_info.
directory() <<
"/neighbours" 1248 << doc_info.
number() <<
".txt";
1249 oomph_info <<
"opened " << fullname.str() <<
" to doc neighbours" 1251 neigh_txt_file.open(fullname.str().c_str());
1255 double max_error=0.0;
1257 neigh_file,neigh_txt_file,max_error);
1262 std::ostringstream error_stream;
1263 error_stream <<
"Max. error in quadtree neighbour finding: " 1264 << max_error <<
" is too big" << std::endl;
1266 <<
"i.e. bigger than Tree::max_neighbour_finding_tolerance()=" 1273 neigh_txt_file.close();
1277 OOMPH_CURRENT_FUNCTION,
1278 OOMPH_EXCEPTION_LOCATION);
1282 oomph_info <<
"Max. error in quadtree neighbour finding: " 1283 << max_error <<
" is OK" << std::endl;
1284 oomph_info <<
"i.e. less than QuadTree::max_neighbour_finding_tolerance()=" 1292 neigh_txt_file.close();
1305 for(
unsigned i=0;
i<4;
i++)
1306 {output_stream.push_back(
new std::ofstream);}
1311 std::ostringstream fullname;
1312 fullname << doc_info.
directory() <<
"/hang_nodes_s" 1313 << doc_info.
number() <<
".dat";
1314 output_stream[0]->open(fullname.str().c_str());
1316 fullname << doc_info.
directory() <<
"/hang_nodes_n" 1317 << doc_info.
number() <<
".dat";
1318 output_stream[1]->open(fullname.str().c_str());
1320 fullname << doc_info.
directory() <<
"/hang_nodes_w" 1321 << doc_info.
number() <<
".dat";
1322 output_stream[2]->open(fullname.str().c_str());
1324 fullname << doc_info.
directory() <<
"/hang_nodes_e" 1325 << doc_info.
number() <<
".dat";
1326 output_stream[3]->open(fullname.str().c_str());
1346 unsigned long num_nodes=all_forest_nodes_pt.size();
1347 for (
unsigned long i=0;
i<num_nodes;
i++)
1349 all_forest_nodes_pt[
i]->object_pt()->set_number(++count);
1354 double max_error=0.0;
1355 std::ofstream neighbours_file;
1356 std::ofstream neighbours_txt_file;
1358 neighbours_txt_file, max_error);
1361 oomph_info <<
"\n \n Failed self_test() for QuadTree: Max. error " 1362 << max_error << std::endl<< std::endl;
1367 oomph_info <<
"\n \n Passed self_test() for QuadTree: Max. error " 1368 << max_error << std::endl<< std::endl;
1383 std::ofstream& neighbours_file,
1384 std::ofstream& neighbours_txt_file,
1387 using namespace QuadTreeNames;
1391 bool in_neighbouring_tree;
1411 unsigned long num_nodes=forest_nodes_pt.size();
1412 for (
unsigned long i=0;
i<num_nodes;
i++)
1415 forest_nodes_pt[
i]->object_pt()->set_number(
i);
1420 for (
unsigned long i=0;
i<num_nodes;
i++)
1430 if (neighbours_file.is_open())
1433 ->
object_pt())->output_corners(neighbours_file,
"BLACK");
1438 for (
int direction=
N;direction<=
W;direction++)
1449 in_neighbouring_tree);
1456 if (neighbours_txt_file.is_open())
1458 neighbours_txt_file << Direct_string[direction]
1459 <<
" neighbour of " <<
1462 <<
" diff_level " << diff_level
1463 <<
" s_diff " << s_diff <<
1464 " inside neighbour the edge is " 1465 << Direct_string[edge] << std::endl
1470 if (neighbours_file.is_open())
1473 output_corners(neighbours_file,Colour[direction]);
1482 if (neighbours_file.is_open())
1484 neighbours_file <<
"ZONE I=2 \n";
1497 s[0]=S_base(0,direction);
1498 s[1]=S_base(1,direction);
1505 bool is_periodic=
false;
1506 if(in_neighbouring_tree)
1515 if(is_periodic==
false)
1517 for(
int i=0;
i<2;
i++)
1519 error += pow(x_small[
i]-x_large[
i],2);
1524 error = sqrt(error);
1525 if (neighbours_txt_file.is_open())
1527 neighbours_txt_file <<
"Error (1) " << error << std::endl;
1530 if (std::fabs(error)>max_error)
1532 max_error=std::fabs(error);
1535 if (neighbours_file.is_open())
1537 neighbours_file << x_large[0] <<
" " << x_large[1] <<
" 0 \n";
1549 s[0]=S_base(0,direction)+S_step(0,direction);
1550 s[1]=S_base(1,direction)+S_step(1,direction);
1555 if(is_periodic==
false)
1557 for(
int i=0;
i<2;
i++)
1559 error += pow(x_small[
i]-x_large[
i],2);
1563 error = sqrt(error);
1567 if (neighbours_txt_file.is_open())
1569 neighbours_txt_file <<
"Error (2) " << error << std::endl;
1572 if (std::fabs(error)>max_error)
1574 max_error=std::fabs(error);
1577 if (neighbours_file.is_open())
1579 neighbours_file << x_large[0] <<
" " << x_large[1] <<
" 0 \n";
1599 if (neighbours_file.is_open())
1601 neighbours_file <<
"ZONE \n 0.00 0.00 0 \n";
1602 neighbours_file <<
"ZONE I=2 \n";
1603 neighbours_file <<
"-0.05 -0.05 0 \n";
1604 neighbours_file <<
"-0.05 -0.05 0 \n";
Vector< Tree * > Son_pt
Vector of pointers to the sons of the Tree.
Vector< TreeRoot * > Trees_pt
Vector containing the pointers to the trees.
static double & max_neighbour_finding_tolerance()
Max. allowed discrepancy in neighbour finding routine (distance between points when identified from t...
unsigned ntree()
Number of trees in forest.
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...
long QuadTreeForest_build
TreeRoot *& neighbour_pt(const int &direction)
Return the pointer to the neighbouring TreeRoots in specified direction. Returns NULL if there's no n...
static bool Static_data_has_been_setup
Bool indicating that static member data has been setup.
bool is_doc_enabled() const
Are we documenting?
void find_neighbours()
Construct the neighbour lookup scheme.
void construct_north_equivalents()
Construct the rotation schemes.
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...
Information for documentation of results: Directory and file number to enable output in the form RESL...
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. 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.
static Vector< std::string > Direct_string
Translate (enumerated) directions into strings.
std::string directory() const
Output directory.
bool is_neighbour_periodic(const int &direction)
Return whether the neighbour in the particular direction is periodic.
void stick_all_tree_nodes_into_vector(Vector< Tree * > &all_forest_nodes)
Traverse forest and stick pointers to all "nodes" into Vector.
static double Max_neighbour_finding_tolerance
Max. allowed discrepancy in neighbour finding routine (distance between points when identified from t...
static DenseMatrix< int > Rotate
Rotate coordinates: If North becomes NorthIs then direction becomes Rotate(NorthIs,direction). E.g. Rotate(E,NW)=NE;.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
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...
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...
TreeRoot * Root_pt
Pointer to the root of the tree.
unsigned & number()
Number used (e.g.) for labeling output files.
long number() const
Element number (for debugging/plotting)
Base class for all quad elements.
static void setup_static_data()
Setup the static data, rotation and reflection schemes, etc.
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...
static DenseMatrix< int > Reflect
Reflection scheme: Reflect(direction,quadrant): Get mirror of quadrant in specified direction...
int Level
Level of the Tree (level 0 = root)
static DenseMatrix< int > Rotate_angle
Angle betwen rotated coordinates: If old_direction becomes new_direction then the angle between the a...
QuadTreeForest()
Default constructor (empty and broken)
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) ...
unsigned self_test()
Self-test: Check all neighbours. Return success (0) if the max. distance between corresponding points...
QuadTreeRoot * quadtree_pt(const unsigned &i)
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...
Tree * Father_pt
Pointer to the Father of the Tree.
virtual bool nodes_built()
Return true if all the nodes have been built, false if not.
static const int OMEGA
Default value for an unassigned neighbour.
int & north_equivalent(const int &neighbour)
Return north equivalent of the neighbours in specified direction: When viewed from the current quadtr...
void stick_all_tree_nodes_into_vector(Vector< Tree * > &)
Traverse and stick pointers to all "nodes" into Vector.
static DenseMatrix< double > S_step
S_step(i,direction) Increments for coordinate s[i] when progressing along the edge indicated by direc...
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...
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.
static DenseMatrix< bool > Is_adjacent
Array of direction/quadrant adjacency scheme: Is_adjacent(i_vertex_or_edge,j_quadrant): Is edge/verte...
RefineableElement * object_pt() const
Return the pointer to the object (RefineableElement) represented by the tree.
int Son_type
Son type (e.g. SW/SE/NW/NE in a quadtree)
static Vector< int > Reflect_edge
Get opposite edge, e.g. Reflect_edge[N]=S.
TreeRoot *& root_pt()
Return pointer to root of the tree.
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...
void resize(const unsigned long &n)