oomph::OcTreeForest Class Reference

#include <octree.h>

+ Inheritance diagram for oomph::OcTreeForest:

Public Member Functions

 OcTreeForest (Vector< TreeRoot * > &trees_pt)
 
 OcTreeForest ()
 Default constructor (empty and broken) More...
 
 OcTreeForest (const OcTreeForest &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const OcTreeForest &)=delete
 Broken assignment operator. More...
 
virtual ~OcTreeForest ()
 
void check_all_neighbours (DocInfo &doc_info)
 
void open_hanging_node_files (DocInfo &doc_info, Vector< std::ofstream * > &output_stream)
 
unsigned self_test ()
 Self test: Check neighbour finding routine. More...
 
OcTreeRootoctree_pt (const unsigned &i) const
 
OcTreeRootoc_face_neigh_pt (const unsigned &i, const int &direction)
 
Vector< TreeRoot * > oc_edge_neigh_pt (const unsigned &i, const int &direction)
 
void construct_up_right_equivalents ()
 Construct the rotation schemes. More...
 
- Public Member Functions inherited from oomph::TreeForest
 TreeForest (Vector< TreeRoot * > &trees_pt)
 
 TreeForest ()
 Default constructor (empty and broken) More...
 
 TreeForest (const TreeForest &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const TreeForest &)=delete
 Broken assignment operator. More...
 
virtual ~TreeForest ()
 Kill tree forest: Delete the constituent trees. More...
 
void stick_leaves_into_vector (Vector< Tree * > &forest_nodes)
 Traverse forst and stick pointers to leaf "nodes" into Vector. More...
 
void stick_all_tree_nodes_into_vector (Vector< Tree * > &all_forest_nodes)
 Traverse forest and stick pointers to all "nodes" into Vector. More...
 
void close_hanging_node_files (DocInfo &doc_info, Vector< std::ofstream * > &output_stream)
 
unsigned ntree ()
 Number of trees in forest. More...
 
TreeRoottree_pt (const unsigned &i) const
 Return pointer to i-th tree in forest. More...
 
void flush_trees ()
 Flush trees from forest. More...
 

Private Member Functions

void find_neighbours ()
 Construct the neighbour scheme. More...
 

Additional Inherited Members

- Protected Attributes inherited from oomph::TreeForest
Vector< TreeRoot * > Trees_pt
 Vector containing the pointers to the trees. More...
 

Detailed Description

/////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// An OcTreeForest consists of a collection of OcTreeRoots. Each member tree can have neighbours to its L/R/U/D/F/B and DB/UP/... and the orientation of their compasses can differ, allowing for complex, unstructured meshes.

Constructor & Destructor Documentation

◆ OcTreeForest() [1/3]

oomph::OcTreeForest::OcTreeForest ( Vector< TreeRoot * > &  trees_pt)

Constructor for OcTree forest: Pass Vector of (pointers to) trees.

/////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// Constructor for OcTreeForest:

Pass:

  • trees_pt[], the Vector of pointers to the constituent trees (OcTreeRoot objects)
4875  : TreeForest(trees_pt)
4876  {
4877 #ifdef LEAK_CHECK
4878  LeakCheckNames::OcTreeForest_build += 1;
4879 #endif
4880 
4881  // Don't setup neighbours etc. if forest is empty
4882  if (trees_pt.size() == 0)
4883  {
4884  return;
4885  }
4886 
4887  using namespace OcTreeNames;
4888 
4889  // Construct the neighbour and rotation scheme, note that all neighbour
4890  // pointers must be set before the constructor is called
4891 
4892  // MemoryUsage::doc_memory_usage(
4893  // "before find_neighbours in octree forest constr");
4894 
4895  // setup the neighbour scheme
4896  find_neighbours();
4897 
4898  // MemoryUsage::doc_memory_usage(
4899  // "after find_neighbours in octree forest constr");
4900 
4901  // setup the rotation scheme
4903 
4904  // MemoryUsage::doc_memory_usage(
4905  // "after construct_up_right_equivalents in octree forest constr");
4906  }
void find_neighbours()
Construct the neighbour scheme.
Definition: octree.cc:4913
void construct_up_right_equivalents()
Construct the rotation schemes.
Definition: octree.cc:5255
TreeForest()
Default constructor (empty and broken)
Definition: tree.h:416

References construct_up_right_equivalents(), and find_neighbours().

◆ OcTreeForest() [2/3]

oomph::OcTreeForest::OcTreeForest ( )
inline

Default constructor (empty and broken)

936  {
937  throw OomphLibError("Don't call empty constructor for OcTreeForest!",
940  }
#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.

◆ OcTreeForest() [3/3]

oomph::OcTreeForest::OcTreeForest ( const OcTreeForest dummy)
delete

Broken copy constructor.

◆ ~OcTreeForest()

virtual oomph::OcTreeForest::~OcTreeForest ( )
inlinevirtual

Destructor: Delete the constituent octrees (and thus the associated objects!)

950 {}

Member Function Documentation

◆ check_all_neighbours()

void oomph::OcTreeForest::check_all_neighbours ( DocInfo doc_info)
virtual

Document and check all the neighbours of all the nodes in the forest. DocInfo object specifies the output directory and file numbers for the various files. If doc_info.disable_doc() has been called, no output is created.

Document and check all the neighbours of all the nodes in the forest. DocInfo object specifies the output directory and file numbers for the various files. If doc_info.is_doc_enabled()=false no output is created.

Implements oomph::TreeForest.

5750  {
5751  // Create vector of all elements in the tree
5752  Vector<Tree*> all_tree_nodes_pt;
5753  this->stick_all_tree_nodes_into_vector(all_tree_nodes_pt);
5754 
5755  // Face neighbours
5756  //----------------
5757  {
5758  // Create storage for the files
5759  std::ofstream neigh_file;
5760  std::ofstream neigh_txt_file;
5761  // If we are documenting, then do so
5762  if (doc_info.is_doc_enabled())
5763  {
5764  std::ostringstream fullname;
5765  fullname << doc_info.directory() << "/neighbours" << doc_info.number()
5766  << ".dat";
5767  oomph_info << "opened " << fullname.str() << " to doc neighbours"
5768  << std::endl;
5769  neigh_file.open(fullname.str().c_str());
5770  fullname.str("");
5771  fullname << doc_info.directory() << "/neighbours" << doc_info.number()
5772  << ".txt";
5773  oomph_info << "opened " << fullname.str() << " to doc neighbours"
5774  << std::endl;
5775  neigh_txt_file.open(fullname.str().c_str());
5776  }
5777 
5778  // Call the static member of OcTree function
5779  double max_error = 0.0;
5781  all_tree_nodes_pt, neigh_file, neigh_txt_file, max_error);
5783  {
5784  std::ostringstream error_stream;
5785  error_stream << "\nMax. error in octree neighbour finding: "
5786  << max_error << " is too big" << std::endl;
5787  error_stream
5788  << "i.e. bigger than Tree::max_neighbour_finding_tolerance()="
5789  << Tree::max_neighbour_finding_tolerance() << std::endl;
5790 
5791  // Close the files if they were opened
5792  if (doc_info.is_doc_enabled())
5793  {
5794  neigh_file.close();
5795  neigh_txt_file.close();
5796  }
5797 
5798  throw OomphLibError(
5799  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
5800  }
5801  else
5802  {
5803  oomph_info << "\nMax. error in octree neighbour finding: " << max_error
5804  << " is OK" << std::endl;
5805  oomph_info
5806  << "i.e. less than OcTree::max_neighbour_finding_tolerance()="
5807  << OcTree::max_neighbour_finding_tolerance() << std::endl;
5808  }
5809 
5810  // Close the documentation files if they were opened
5811  if (doc_info.is_doc_enabled())
5812  {
5813  neigh_file.close();
5814  neigh_txt_file.close();
5815  }
5816  }
5817 
5818  // Edge neighbours
5819  //----------------
5820  {
5821  // Create storage for the files
5822  std::ofstream neigh_file;
5823  std::ofstream no_true_edge_file;
5824  std::ofstream neigh_txt_file;
5825  // If we are documenting, then do so
5826  if (doc_info.is_doc_enabled())
5827  {
5828  std::ostringstream fullname;
5829  fullname << doc_info.directory() << "/edge_neighbours"
5830  << doc_info.number() << ".dat";
5831  neigh_file.open(fullname.str().c_str());
5832  fullname.str("");
5833  fullname << doc_info.directory() << "/no_true_edge" << doc_info.number()
5834  << ".dat";
5835  no_true_edge_file.open(fullname.str().c_str());
5836  fullname.str("");
5837  fullname << doc_info.directory() << "/edge_neighbours"
5838  << doc_info.number() << ".txt";
5839  neigh_txt_file.open(fullname.str().c_str());
5840  }
5841 
5842  // Call the static member of OcTree function
5843  double max_error = 0.0;
5844  // Get the maximum error between edge neighbours
5845  OcTree::doc_true_edge_neighbours(all_tree_nodes_pt,
5846  neigh_file,
5847  no_true_edge_file,
5848  neigh_txt_file,
5849  max_error);
5851  {
5852  std::ostringstream error_stream;
5853  error_stream << "Max. error in octree edge neighbour finding: "
5854  << max_error << " is too big" << std::endl;
5855  error_stream
5856  << "i.e. bigger than Tree::max_neighbour_finding_tolerance()="
5857  << Tree::max_neighbour_finding_tolerance() << std::endl;
5858 
5859  // Close the files if they were opened
5860  if (doc_info.is_doc_enabled())
5861  {
5862  neigh_file.close();
5863  no_true_edge_file.close();
5864  neigh_txt_file.close();
5865  }
5866 
5867  throw OomphLibError(
5868  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
5869  }
5870  else
5871  {
5872  oomph_info << "Max. error in octree edge neighbour finding: "
5873  << max_error << " is OK" << std::endl;
5874  oomph_info
5875  << "i.e. less than OcTree::max_neighbour_finding_tolerance()="
5876  << OcTree::max_neighbour_finding_tolerance() << std::endl;
5877  }
5878 
5879  // Close the documentation files if they were opened
5880  if (doc_info.is_doc_enabled())
5881  {
5882  neigh_file.close();
5883  no_true_edge_file.close();
5884  neigh_txt_file.close();
5885  }
5886  }
5887  }
static void doc_true_edge_neighbours(Vector< Tree * > forest_nodes_pt, std::ofstream &neighbours_file, std::ofstream &no_true_edge_file, std::ofstream &neighbours_txt_file, double &max_error)
Definition: octree.cc:4552
static void doc_face_neighbours(Vector< Tree * > forest_nodes_pt, std::ofstream &neighbours_file, std::ofstream &neighbours_txt_file, double &max_error)
Definition: octree.cc:4275
void stick_all_tree_nodes_into_vector(Vector< Tree * > &all_forest_nodes)
Traverse forest and stick pointers to all "nodes" into Vector.
Definition: tree.cc:405
static double & max_neighbour_finding_tolerance()
Definition: tree.h:255
double max_error
Definition: MortaringCantileverCompareToNonMortaring.cpp:188
OomphInfo oomph_info
Definition: oomph_definitions.cc:319

References oomph::DocInfo::directory(), oomph::OcTree::doc_face_neighbours(), oomph::OcTree::doc_true_edge_neighbours(), oomph::DocInfo::is_doc_enabled(), MeshRefinement::max_error, oomph::Tree::max_neighbour_finding_tolerance(), oomph::DocInfo::number(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::oomph_info, and oomph::TreeForest::stick_all_tree_nodes_into_vector().

◆ construct_up_right_equivalents()

void oomph::OcTreeForest::construct_up_right_equivalents ( )

Construct the rotation schemes.

Construct the rotation scheme for the octree forest. Note that all pointers to neighbours must have been allocated for this to work.

5256  {
5257  using namespace OcTreeNames;
5258 
5259  // Number of trees in forest
5260  unsigned numtrees = ntree();
5261 
5262  // nnode1d from first element (if it exists!)
5263  int nnode1d = 0;
5264  if (numtrees > 0)
5265  {
5266  nnode1d = Trees_pt[0]->object_pt()->nnode_1d();
5267  }
5268 
5269  OcTreeRoot* neigh_pt = 0;
5270 
5271  // Loop over all the trees
5272  //------------------------
5273  for (unsigned i = 0; i < numtrees; i++)
5274  {
5275  // Find the pointer to the Up neighbour
5276  //------------------------------------
5277  neigh_pt = oc_face_neigh_pt(i, U);
5278 
5279  // If there is a neighbour?
5280  if (neigh_pt != 0)
5281  {
5282  // Find the direction of the present tree, as viewed from the neighbour
5283  int direction = neigh_pt->direction_of_neighbour(octree_pt(i));
5284 
5285  // If up neighbour has a pointer to this tree
5286  if (direction != Tree::OMEGA)
5287  {
5288  // The direction to the element in the neighbour
5289  // must be equivalent to the down direction in this element
5290  // Hence, the up equivalent is the reflection of that direction
5291  octree_pt(i)->set_up_equivalent(neigh_pt,
5292  OcTree::Reflect_face[direction]);
5293 
5294  // The right equivalent is the direction to the equivalent of
5295  // the right face in the present element, which will
5296  // be connected to the UR edge of the present element,
5297  // but will not be the face adjacent to the U boundary
5298  // i.e. the "direction" face.
5299  // We find the local node numbers, in the neighbour, of
5300  // the UR edge of the present element
5301  int nod1 = neigh_pt->object_pt()->get_node_number(
5302  octree_pt(i)->object_pt()->node_pt(nnode1d * nnode1d * nnode1d -
5303  1));
5304  int nod2 = neigh_pt->object_pt()->get_node_number(
5305  octree_pt(i)->object_pt()->node_pt(nnode1d * nnode1d - 1));
5306 
5307  // Now get the other face connected to that edge in the
5308  // neighbour. It is the right equivalent
5310  neigh_pt,
5311  OcTree::get_the_other_face(nod1, nod2, nnode1d, direction));
5312  }
5313  else
5314  // If U neighbour does not have pointer to this tree, die
5315  {
5316  std::ostringstream error_stream;
5317  error_stream << "Tree " << i
5318  << "'s Up neighbour has no neighbour pointer to Tree "
5319  << i << std::endl;
5320 
5321  throw OomphLibError(error_stream.str(),
5324  }
5325  }
5326 
5327 
5328  // Find the pointer to the Right neighbour
5329  //---------------------------------------
5330  neigh_pt = oc_face_neigh_pt(i, R);
5331 
5332  // If there is a neighbour?
5333  if (neigh_pt != 0)
5334  {
5335  // Find the direction of the present tree, as viewed from the neighbour
5336  int direction = neigh_pt->direction_of_neighbour(octree_pt(i));
5337 
5338  // If the neighbour has a pointer to this tree
5339  if (direction != Tree::OMEGA)
5340  {
5341  // The direction to the element in the neighbour
5342  // must be equivalent to the left direction in this element
5343  // Hence, the right equivalent is the reflection of that direction
5344  octree_pt(i)->set_right_equivalent(neigh_pt,
5345  OcTree::Reflect_face[direction]);
5346 
5347  // The up equivalent will be the direction to the equivalent of
5348  // the up face in the neighbour, which will be connected to the
5349  // UR edge of the present element, but will not be the face
5350  // adjacent to the R boundary, i.e. the "direction" face
5351  // We find the local node numbers, in the neighbour, of the
5352  // UR edge of the present element
5353  int nod1 = neigh_pt->object_pt()->get_node_number(
5354  octree_pt(i)->object_pt()->node_pt(nnode1d * nnode1d * nnode1d -
5355  1));
5356  int nod2 = neigh_pt->object_pt()->get_node_number(
5357  octree_pt(i)->object_pt()->node_pt(nnode1d * nnode1d - 1));
5358 
5359  // Now get the other face connected to that edge in the
5360  // neighbour. It is the up equivalent
5362  neigh_pt,
5363  OcTree::get_the_other_face(nod1, nod2, nnode1d, direction));
5364  }
5365  else
5366  {
5367  // If R neighbour does not have pointer to this tree, die
5368  std::ostringstream error_stream;
5369  error_stream << "Tree " << i
5370  << "'s Right neighbour has no neighbour pointer to Tree "
5371  << i << std::endl;
5372 
5373  throw OomphLibError(error_stream.str(),
5376  }
5377  }
5378 
5379 
5380  // Find the pointer to the Down neighbour
5381  //--------------------------------------
5382  neigh_pt = oc_face_neigh_pt(i, D);
5383 
5384  // If there is a neighbour?
5385  if (neigh_pt != 0)
5386  {
5387  // Find the direction of the present tree, as viewed from the neighbour
5388  int direction = neigh_pt->direction_of_neighbour(octree_pt(i));
5389 
5390  // If the neighbour has a pointer to this element
5391  if (direction != Tree::OMEGA)
5392  {
5393  // The direction to the element in the neighbour must be
5394  // equivalent to the up direction
5395  octree_pt(i)->set_up_equivalent(neigh_pt, direction);
5396 
5397  // The right equivalent is the direction to the equivalent of
5398  // the right face in the present element, which will be
5399  // connected to the DR edge of the present element, but will
5400  // not be the face adjacent to the D boundary,
5401  // i.e. the "direction" face.
5402  // We find the local node numbers, in the neighbour, of
5403  // the RD edge of the present element
5404  int nod1 = neigh_pt->object_pt()->get_node_number(
5405  octree_pt(i)->object_pt()->node_pt(nnode1d - 1));
5406  int nod2 = neigh_pt->object_pt()->get_node_number(
5407  octree_pt(i)->object_pt()->node_pt((nnode1d * nnode1d + 1) *
5408  (nnode1d - 1)));
5409 
5410  // Now get the other face connected to that edge in the neighbour.
5411  // It is the right equivalent
5413  neigh_pt,
5414  OcTree::get_the_other_face(nod1, nod2, nnode1d, direction));
5415  }
5416  else
5417  {
5418  // If D neighbour does not have pointer to this tree, die
5419  std::ostringstream error_stream;
5420  error_stream << "Tree " << i
5421  << "'s Down neighbour has no neighbour pointer to Tree "
5422  << i << std::endl;
5423 
5424  throw OomphLibError(error_stream.str(),
5427  }
5428  }
5429 
5430 
5431  // Find the pointer to the Left neighbour
5432  //--------------------------------------
5433  neigh_pt = oc_face_neigh_pt(i, L);
5434 
5435  // If there is a neighbour
5436  if (neigh_pt != 0)
5437  {
5438  // Find the direction of the present tree, as viewed from the neighbour
5439  int direction = neigh_pt->direction_of_neighbour(octree_pt(i));
5440 
5441  // If the neighbour has a pointer to the present element
5442  if (direction != Tree::OMEGA)
5443  {
5444  // The direction to the element in the neighbour is
5445  // must be equivalent to the right direction
5446  octree_pt(i)->set_right_equivalent(neigh_pt, direction);
5447 
5448  // The up equivalent is the direction to the equivalent of the
5449  // up face in the present element, which will be connected to
5450  // the UL edge of the present element, but will not
5451  // be the face adjacent to the L boundary, i.e. the "direction"
5452  // face.
5453  // We find the local node numbers, in the neighbour, of the UL
5454  // edge
5455  int nod1 = neigh_pt->object_pt()->get_node_number(
5456  octree_pt(i)->object_pt()->node_pt((nnode1d - 1) * nnode1d));
5457  int nod2 = neigh_pt->object_pt()->get_node_number(
5458  octree_pt(i)->object_pt()->node_pt((nnode1d * nnode1d - 1) *
5459  nnode1d));
5460 
5461  // Now get the other face connected to that edge in the
5462  // neighbour.It is the up equivalent
5464  neigh_pt,
5465  OcTree::get_the_other_face(nod1, nod2, nnode1d, direction));
5466  }
5467  else
5468  {
5469  // If L neighbour does not have pointer to this tree, die
5470  std::ostringstream error_stream;
5471  error_stream << "Tree " << i
5472  << "'s Left neighbour has no neighbour pointer to Tree "
5473  << i << std::endl;
5474 
5475  throw OomphLibError(error_stream.str(),
5478  }
5479  }
5480 
5481 
5482  // Find the pointer to the Front neighbour
5483  //---------------------------------------
5484  neigh_pt = oc_face_neigh_pt(i, F);
5485 
5486  // If there is a neighbour?
5487  if (neigh_pt != 0)
5488  {
5489  // Find the direction of the present tree, as viewed from the neighbour
5490  int direction = neigh_pt->direction_of_neighbour(octree_pt(i));
5491 
5492  // If the neighbour has a pointer to the present element
5493  if (direction != Tree::OMEGA)
5494  {
5495  // The direction to the up face will be given by the
5496  // other face connected to the UF edge in the neighbour
5497  // i.e. the face that is not given by direction
5498  // We obtain the local node numbers, in the neighbour,
5499  // of the UF edge in the present element
5500  int nod1 = neigh_pt->object_pt()->get_node_number(
5501  octree_pt(i)->object_pt()->node_pt(nnode1d * nnode1d * nnode1d -
5502  1));
5503  int nod2 = neigh_pt->object_pt()->get_node_number(
5504  octree_pt(i)->object_pt()->node_pt((nnode1d * nnode1d - 1) *
5505  nnode1d));
5506 
5507  // We now get the other face connected to that edge
5508  // It is the up equivalent.
5510  neigh_pt,
5511  OcTree::get_the_other_face(nod1, nod2, nnode1d, direction));
5512 
5513  // The direction to the right face will be given by the
5514  // other face connected to the RF edge in the neighbour
5515  // i.e. the face that is not given by the direction
5516  // We get the local node numbers, in the neighbour,
5517  // of the RF edge in the present element
5518  nod1 = neigh_pt->object_pt()->get_node_number(
5519  octree_pt(i)->object_pt()->node_pt(nnode1d * nnode1d * nnode1d -
5520  1));
5521  nod2 = neigh_pt->object_pt()->get_node_number(
5522  octree_pt(i)->object_pt()->node_pt((nnode1d * nnode1d + 1) *
5523  (nnode1d - 1)));
5524 
5525  // We now get the other face connected to that edge
5526  // It is the right equivalent
5528  neigh_pt,
5529  OcTree::get_the_other_face(nod1, nod2, nnode1d, direction));
5530  }
5531  else
5532  {
5533  // If F neighbour does not have pointer to this tree, die
5534  std::ostringstream error_stream;
5535  error_stream << "Tree " << i
5536  << "'s Front neighbour has no neighbour pointer to Tree "
5537  << i << std::endl;
5538 
5539  throw OomphLibError(error_stream.str(),
5542  }
5543  }
5544 
5545 
5546  // Find the pointer to the Back neighbour
5547  //--------------------------------------
5548  neigh_pt = oc_face_neigh_pt(i, B);
5549 
5550  // If there is a neighbour?
5551  if (neigh_pt != 0)
5552  {
5553  // Find the direction of the present tree, as viewed from the neighbour
5554  int direction = neigh_pt->direction_of_neighbour(octree_pt(i));
5555 
5556  // If the neighbour has a pointer to the present element
5557  if (direction != Tree::OMEGA)
5558  {
5559  // The direction to the up face will be given by the
5560  // other face connected to the UB edge of the present element
5561  // i.e. not the "direction" face
5562  // We obtain the local node numbers, in the neighbour,
5563  // of the UB edge in the present element
5564  int nod1 = neigh_pt->object_pt()->get_node_number(
5565  octree_pt(i)->object_pt()->node_pt((nnode1d - 1) * nnode1d));
5566  int nod2 = neigh_pt->object_pt()->get_node_number(
5567  octree_pt(i)->object_pt()->node_pt(nnode1d * nnode1d - 1));
5568 
5569  // We now get the other face connected to that edge
5570  // It is the up equivalent
5572  neigh_pt,
5573  OcTree::get_the_other_face(nod1, nod2, nnode1d, direction));
5574 
5575  // The direction to the right face will be given by
5576  // the other face connected to the RB edge of the present
5577  // element, i.e. not the direction face.
5578  // We obtain local node numbers, in the neighbour,
5579  // of the RB edge in the present element
5580  nod1 = neigh_pt->object_pt()->get_node_number(
5581  octree_pt(i)->object_pt()->node_pt(nnode1d * nnode1d - 1));
5582  nod2 = neigh_pt->object_pt()->get_node_number(
5583  octree_pt(i)->object_pt()->node_pt(nnode1d - 1));
5584 
5585  // We now get the other face connected to that edge
5586  // It is the right equivalent
5588  neigh_pt,
5589  OcTree::get_the_other_face(nod1, nod2, nnode1d, direction));
5590  }
5591  else
5592  {
5593  // If B neighbour does not have pointer to this tree, die
5594  std::ostringstream error_stream;
5595  error_stream << "Tree " << i
5596  << "'s Back neighbour has no neighbour pointer to Tree "
5597  << i << std::endl;
5598 
5599  throw OomphLibError(error_stream.str(),
5602  }
5603  }
5604 
5605 
5606  // EDGE NEIGHBOURS
5607  //----------------
5608 
5609  // Loop over all edges:
5610  for (int edge = LB; edge <= UF; edge++)
5611  {
5612  // Get vector to pointers of edge neighbours
5613  Vector<TreeRoot*> edge_neigh_pt = oc_edge_neigh_pt(i, edge);
5614 
5615  // Loop over all edge neighbours
5616  unsigned n_neigh = edge_neigh_pt.size();
5617  for (unsigned e = 0; e < n_neigh; e++)
5618  {
5619  // If there is a neighbour
5620  if (edge_neigh_pt[e] != 0)
5621  {
5622  // Here are the two vertices at the two ends of the edge
5623  // in the present element
5624  int vertex = OcTree::Vertex_at_end_of_edge[edge][0];
5625  int other_vertex = OcTree::Vertex_at_end_of_edge[edge][1];
5626 
5627  // Get node numbers of the two vertices on edge
5628  unsigned nod1 = OcTree::vertex_to_node_number(vertex, nnode1d);
5629  unsigned nod2 =
5630  OcTree::vertex_to_node_number(other_vertex, nnode1d);
5631 
5632 
5633  // Here are the local node numbers (in the neighbouring element)
5634  // of the start/end nodes of present element's edge:
5635  unsigned neighb_nod1 =
5636  edge_neigh_pt[e]->object_pt()->get_node_number(
5637  octree_pt(i)->object_pt()->node_pt(nod1));
5638 
5639  unsigned neighb_nod2 =
5640  edge_neigh_pt[e]->object_pt()->get_node_number(
5641  octree_pt(i)->object_pt()->node_pt(nod2));
5642 
5643  // Convert to vertices
5644  int neighb_vertex =
5645  OcTree::node_number_to_vertex(neighb_nod1, nnode1d);
5646  int neighb_other_vertex =
5647  OcTree::node_number_to_vertex(neighb_nod2, nnode1d);
5648 
5649  // Up equivalent is stored first in the pair that's returned
5650  // by the lookup table
5652  edge_neigh_pt[e],
5654  [std::make_pair(
5655  std::make_pair(neighb_vertex, vertex),
5656  std::make_pair(neighb_other_vertex, other_vertex))]
5657  .first);
5658 
5659  // Right equivalent is stored second in the pair that's returned
5660  // by the lookup table
5662  edge_neigh_pt[e],
5664  [std::make_pair(
5665  std::make_pair(neighb_vertex, vertex),
5666  std::make_pair(neighb_other_vertex, other_vertex))]
5667  .second);
5668  }
5669  }
5670  }
5671  } // end of loop over all trees.
5672  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
dominoes D
Definition: Domino.cpp:55
MatrixXd L
Definition: LLT_example.cpp:6
@ R
Definition: StatisticsVector.h:21
Definition: matrices.h:74
Vector< TreeRoot * > oc_edge_neigh_pt(const unsigned &i, const int &direction)
Definition: octree.h:1002
OcTreeRoot * oc_face_neigh_pt(const unsigned &i, const int &direction)
Definition: octree.h:982
OcTreeRoot * octree_pt(const unsigned &i) const
Definition: octree.h:973
void set_up_equivalent(TreeRoot *tree_root_pt, const int &dir)
Definition: octree.h:779
void set_right_equivalent(TreeRoot *tree_root_pt, const int &dir)
Definition: octree.h:806
static int node_number_to_vertex(const unsigned &n, const unsigned &nnode1d)
Definition: octree.cc:491
static Vector< int > Reflect_face
Get opposite face, e.g. Reflect_face[L]=R.
Definition: octree.h:332
static std::map< std::pair< std::pair< int, int >, std::pair< int, int > >, std::pair< int, int > > Up_and_right_equivalent_for_pairs_of_vertices
Definition: octree.h:377
static int get_the_other_face(const unsigned &n1, const unsigned &n2, const unsigned &nnode1d, const int &face)
Definition: octree.cc:565
static Vector< Vector< int > > Vertex_at_end_of_edge
Map of vectors containing the two vertices for each edge.
Definition: octree.h:343
static unsigned vertex_to_node_number(const int &vertex, const unsigned &nnode1d)
Definition: octree.cc:414
unsigned ntree()
Number of trees in forest.
Definition: tree.h:460
Vector< TreeRoot * > Trees_pt
Vector containing the pointers to the trees.
Definition: tree.h:480
static const int OMEGA
Default value for an unassigned neighbour.
Definition: tree.h:262
double U
Swimming speed.
Definition: two_d_variable_diff_adapt.cc:53
@ UF
Definition: octree.h:68
@ F
Definition: octree.h:74
@ LB
Definition: octree.h:57

References D, oomph::OcTreeRoot::direction_of_neighbour(), e(), oomph::OcTreeNames::F, oomph::FiniteElement::get_node_number(), oomph::OcTree::get_the_other_face(), i, L, oomph::OcTreeNames::LB, oomph::OcTree::node_number_to_vertex(), oomph::TreeForest::ntree(), oomph::Tree::object_pt(), oc_edge_neigh_pt(), oc_face_neigh_pt(), octree_pt(), oomph::Tree::OMEGA, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, R, oomph::OcTree::Reflect_face, oomph::OcTreeRoot::set_right_equivalent(), oomph::OcTreeRoot::set_up_equivalent(), oomph::TreeForest::Trees_pt, RachelsAdvectionDiffusion::U, oomph::OcTreeNames::UF, oomph::OcTree::Up_and_right_equivalent_for_pairs_of_vertices, oomph::OcTree::Vertex_at_end_of_edge, and oomph::OcTree::vertex_to_node_number().

Referenced by OcTreeForest().

◆ find_neighbours()

void oomph::OcTreeForest::find_neighbours ( )
private

Construct the neighbour scheme.

setup the neighbour scheme : tells to each element in the forest which (if any) element is its {R,L,U,D,B,F} face neighbour and which is its {LB,RB,...,UF} edge neighbour.

4914  {
4915  using namespace OcTreeNames;
4916  unsigned numtrees = ntree();
4917  int n = 0; // to store nnode1d
4918  if (numtrees > 0)
4919  {
4920  n = Trees_pt[0]->object_pt()->nnode_1d();
4921  }
4922  else
4923  {
4924  throw OomphLibError(
4925  "Trying to setup the neighbour scheme for an empty forest",
4928  }
4929 
4930 
4931  // Number of vertex nodes: 8
4932  unsigned n_vertex_node = 8;
4933 
4934  // Find potentially connected trees by identifying
4935  // those whose associated elements share a common vertex node
4936  std::map<Node*, std::set<unsigned>> tree_assoc_with_vertex_node;
4937 
4938  // Loop over all trees
4939  for (unsigned i = 0; i < numtrees; i++)
4940  {
4941  // Loop over the vertex nodes of the associated element
4942  for (unsigned j = 0; j < n_vertex_node; j++)
4943  {
4944  Node* nod_pt = dynamic_cast<BrickElementBase*>(Trees_pt[i]->object_pt())
4945  ->vertex_node_pt(j);
4946  tree_assoc_with_vertex_node[nod_pt].insert(i);
4947  }
4948  }
4949 
4950 
4951  // For each tree we store a set of potentially neighbouring trees
4952  // i.e. trees that share at least one node
4953  Vector<std::set<unsigned>> potentially_neighb_tree(numtrees);
4954 
4955  // Loop over vertex nodes
4956  for (std::map<Node*, std::set<unsigned>>::iterator it =
4957  tree_assoc_with_vertex_node.begin();
4958  it != tree_assoc_with_vertex_node.end();
4959  it++)
4960  {
4961  // Loop over connected elements twice
4962  for (std::set<unsigned>::iterator it_el1 = it->second.begin();
4963  it_el1 != it->second.end();
4964  it_el1++)
4965  {
4966  unsigned i = (*it_el1);
4967  for (std::set<unsigned>::iterator it_el2 = it->second.begin();
4968  it_el2 != it->second.end();
4969  it_el2++)
4970  {
4971  unsigned j = (*it_el2);
4972  // These two elements are potentially connected
4973  if (i != j)
4974  {
4975  potentially_neighb_tree[i].insert(j);
4976  }
4977  }
4978  }
4979  }
4980 
4981 
4982  // Loop over all trees
4983  for (unsigned i = 0; i < numtrees; i++)
4984  {
4985  // Cast to OcTreeRoot
4986  OcTreeRoot* octree_root_i_pt = dynamic_cast<OcTreeRoot*>(Trees_pt[i]);
4987 
4988  // Loop over their potential neighbours
4989  for (std::set<unsigned>::iterator it = potentially_neighb_tree[i].begin();
4990  it != potentially_neighb_tree[i].end();
4991  it++)
4992  {
4993  unsigned j = (*it);
4994 
4995  // So far, we haven't identified the candidate element as a face
4996  // neighbour of element/tree i
4997  bool is_face_neighbour = false;
4998 
4999  // is it the Up neighbour ?
5000  bool is_Up_neighbour =
5001  ((Trees_pt[j]->object_pt()->get_node_number(
5002  Trees_pt[i]->object_pt()->node_pt(n * (n * n - 1))) != -1) &&
5003  (Trees_pt[j]->object_pt()->get_node_number(
5004  Trees_pt[i]->object_pt()->node_pt(n * n - 1)) != -1));
5005 
5006  // is it the Down neighbour ?
5007  bool is_Down_neighbour =
5008  ((Trees_pt[j]->object_pt()->get_node_number(
5009  Trees_pt[i]->object_pt()->node_pt(n * n * (n - 1))) != -1) &&
5010  (Trees_pt[j]->object_pt()->get_node_number(
5011  Trees_pt[i]->object_pt()->node_pt(n - 1)) != -1));
5012 
5013  // is it the Right neighbour ?
5014  bool is_Right_neighbour =
5015  ((Trees_pt[j]->object_pt()->get_node_number(
5016  Trees_pt[i]->object_pt()->node_pt(n * n * n - 1)) != -1) &&
5017  (Trees_pt[j]->object_pt()->get_node_number(
5018  Trees_pt[i]->object_pt()->node_pt(n - 1)) != -1));
5019 
5020  // is it the Left neighbour ?
5021  bool is_Left_neighbour =
5022  ((Trees_pt[j]->object_pt()->get_node_number(
5023  Trees_pt[i]->object_pt()->node_pt(n * (n * n - 1))) != -1) &&
5024  (Trees_pt[j]->object_pt()->get_node_number(
5025  Trees_pt[i]->object_pt()->node_pt(0)) != -1));
5026 
5027  // is it the Back neighbour ?
5028  bool is_Back_neighbour =
5029  ((Trees_pt[j]->object_pt()->get_node_number(
5030  Trees_pt[i]->object_pt()->node_pt(n * n - 1)) != -1) &&
5031  (Trees_pt[j]->object_pt()->get_node_number(
5032  Trees_pt[i]->object_pt()->node_pt(0)) != -1));
5033 
5034  // is it the Front neighbour ?
5035  bool is_Front_neighbour =
5036  ((Trees_pt[j]->object_pt()->get_node_number(
5037  Trees_pt[i]->object_pt()->node_pt(n * n * n - 1)) != -1) &&
5038  (Trees_pt[j]->object_pt()->get_node_number(
5039  Trees_pt[i]->object_pt()->node_pt(n * n * (n - 1))) != -1));
5040 
5041 
5042  if (is_Down_neighbour)
5043  {
5044  is_face_neighbour = true;
5045  Trees_pt[i]->neighbour_pt(D) = Trees_pt[j];
5046  }
5047  if (is_Up_neighbour)
5048  {
5049  is_face_neighbour = true;
5050  Trees_pt[i]->neighbour_pt(U) = Trees_pt[j];
5051  }
5052  if (is_Right_neighbour)
5053  {
5054  is_face_neighbour = true;
5055  Trees_pt[i]->neighbour_pt(R) = Trees_pt[j];
5056  }
5057  if (is_Left_neighbour)
5058  {
5059  is_face_neighbour = true;
5060  Trees_pt[i]->neighbour_pt(L) = Trees_pt[j];
5061  }
5062  if (is_Back_neighbour)
5063  {
5064  is_face_neighbour = true;
5065  Trees_pt[i]->neighbour_pt(B) = Trees_pt[j];
5066  }
5067  if (is_Front_neighbour)
5068  {
5069  is_face_neighbour = true;
5070  Trees_pt[i]->neighbour_pt(F) = Trees_pt[j];
5071  }
5072 
5073 
5074  // If it's not a face neighbour, it may still be an edge
5075  // neighbour. We check this by checking if the
5076  // vertex nodes coincide. Note: This test would also
5077  // evaluate to true for face neighbours but we've already
5078  // determined that the element is not a face neighbour!
5079  if (!is_face_neighbour)
5080  {
5081  // is it the left back neighbour ?
5082  bool is_left_back_neighbour =
5083  ((Trees_pt[j]->object_pt()->get_node_number(
5084  Trees_pt[i]->object_pt()->node_pt(0)) != -1) &&
5085  (Trees_pt[j]->object_pt()->get_node_number(
5086  Trees_pt[i]->object_pt()->node_pt(n * (n - 1))) != -1));
5087 
5088  // is it the right back neighbour ?
5089  bool is_right_back_neighbour =
5090  ((Trees_pt[j]->object_pt()->get_node_number(
5091  Trees_pt[i]->object_pt()->node_pt(n - 1)) != -1) &&
5092  (Trees_pt[j]->object_pt()->get_node_number(
5093  Trees_pt[i]->object_pt()->node_pt(n * n - 1)) != -1));
5094 
5095 
5096  // is it the down back neighbour ?
5097  bool is_down_back_neighbour =
5098  ((Trees_pt[j]->object_pt()->get_node_number(
5099  Trees_pt[i]->object_pt()->node_pt(n - 1)) != -1) &&
5100  (Trees_pt[j]->object_pt()->get_node_number(
5101  Trees_pt[i]->object_pt()->node_pt(0)) != -1));
5102 
5103  // is it the up back neighbour ?
5104  bool is_up_back_neighbour =
5105  ((Trees_pt[j]->object_pt()->get_node_number(
5106  Trees_pt[i]->object_pt()->node_pt(n * (n - 1))) != -1) &&
5107  (Trees_pt[j]->object_pt()->get_node_number(
5108  Trees_pt[i]->object_pt()->node_pt(n * n - 1)) != -1));
5109 
5110 
5111  // is it the left down neighbour ?
5112  bool is_left_down_neighbour =
5113  ((Trees_pt[j]->object_pt()->get_node_number(
5114  Trees_pt[i]->object_pt()->node_pt(n * n * (n - 1))) != -1) &&
5115  (Trees_pt[j]->object_pt()->get_node_number(
5116  Trees_pt[i]->object_pt()->node_pt(0)) != -1));
5117 
5118 
5119  // is it the right down neighbour ?
5120  bool is_right_down_neighbour =
5121  ((Trees_pt[j]->object_pt()->get_node_number(
5122  Trees_pt[i]->object_pt()->node_pt((n * n + 1) * (n - 1))) !=
5123  -1) &&
5124  (Trees_pt[j]->object_pt()->get_node_number(
5125  Trees_pt[i]->object_pt()->node_pt(n - 1)) != -1));
5126 
5127 
5128  // is it the left up neighbour ?
5129  bool is_left_up_neighbour =
5130  ((Trees_pt[j]->object_pt()->get_node_number(
5131  Trees_pt[i]->object_pt()->node_pt((n * n * n - n))) != -1) &&
5132  (Trees_pt[j]->object_pt()->get_node_number(
5133  Trees_pt[i]->object_pt()->node_pt(n * (n - 1))) != -1));
5134 
5135 
5136  // is it the right up neighbour ?
5137  bool is_right_up_neighbour =
5138  ((Trees_pt[j]->object_pt()->get_node_number(
5139  Trees_pt[i]->object_pt()->node_pt((n * n * n - 1))) != -1) &&
5140  (Trees_pt[j]->object_pt()->get_node_number(
5141  Trees_pt[i]->object_pt()->node_pt(n * n - 1)) != -1));
5142 
5143 
5144  // is it the left front neighbour ?
5145  bool is_left_front_neighbour =
5146  ((Trees_pt[j]->object_pt()->get_node_number(
5147  Trees_pt[i]->object_pt()->node_pt((n * n * n - n))) != -1) &&
5148  (Trees_pt[j]->object_pt()->get_node_number(
5149  Trees_pt[i]->object_pt()->node_pt(n * n * (n - 1))) != -1));
5150 
5151 
5152  // is it the right front neighbour ?
5153  bool is_right_front_neighbour =
5154  ((Trees_pt[j]->object_pt()->get_node_number(
5155  Trees_pt[i]->object_pt()->node_pt((n * n * n - 1))) != -1) &&
5156  (Trees_pt[j]->object_pt()->get_node_number(
5157  Trees_pt[i]->object_pt()->node_pt((n * n + 1) * (n - 1))) !=
5158  -1));
5159 
5160 
5161  // is it the down front neighbour ?
5162  bool is_down_front_neighbour =
5163  ((Trees_pt[j]->object_pt()->get_node_number(
5164  Trees_pt[i]->object_pt()->node_pt(n * n * (n - 1))) != -1) &&
5165  (Trees_pt[j]->object_pt()->get_node_number(
5166  Trees_pt[i]->object_pt()->node_pt((n * n + 1) * (n - 1))) !=
5167  -1));
5168 
5169 
5170  // is it the up front neighbour ?
5171  bool is_up_front_neighbour =
5172  ((Trees_pt[j]->object_pt()->get_node_number(
5173  Trees_pt[i]->object_pt()->node_pt((n * n * n - n))) != -1) &&
5174  (Trees_pt[j]->object_pt()->get_node_number(
5175  Trees_pt[i]->object_pt()->node_pt((n * n * n - 1))) != -1));
5176 
5177 
5178  // Add to storage scheme for edge neighbours (only!)
5179 
5180  if (is_left_back_neighbour)
5181  {
5182  // Trees_pt[i]->neighbour_pt(LB)=Trees_pt[j];
5183  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], LB);
5184  }
5185  if (is_right_back_neighbour)
5186  {
5187  // Trees_pt[i]->neighbour_pt(RB)=Trees_pt[j];
5188  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], RB);
5189  }
5190  if (is_down_back_neighbour)
5191  {
5192  // Trees_pt[i]->neighbour_pt(DB)=Trees_pt[j];
5193  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], DB);
5194  }
5195  if (is_up_back_neighbour)
5196  {
5197  // Trees_pt[i]->neighbour_pt(UB)=Trees_pt[j];
5198  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], UB);
5199  }
5200 
5201 
5202  if (is_left_down_neighbour)
5203  {
5204  // Trees_pt[i]->neighbour_pt(LD)=Trees_pt[j];
5205  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], LD);
5206  }
5207  if (is_right_down_neighbour)
5208  {
5209  // Trees_pt[i]->neighbour_pt(RD)=Trees_pt[j];
5210  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], RD);
5211  }
5212  if (is_left_up_neighbour)
5213  {
5214  // Trees_pt[i]->neighbour_pt(LU)=Trees_pt[j];
5215  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], LU);
5216  }
5217  if (is_right_up_neighbour)
5218  {
5219  // Trees_pt[i]->neighbour_pt(RU)=Trees_pt[j];
5220  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], RU);
5221  }
5222 
5223 
5224  if (is_left_front_neighbour)
5225  {
5226  // Trees_pt[i]->neighbour_pt(LF)=Trees_pt[j];
5227  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], LF);
5228  }
5229  if (is_right_front_neighbour)
5230  {
5231  // Trees_pt[i]->neighbour_pt(RF)=Trees_pt[j];
5232  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], RF);
5233  }
5234  if (is_down_front_neighbour)
5235  {
5236  // Trees_pt[i]->neighbour_pt(DF)=Trees_pt[j];
5237  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], DF);
5238  }
5239  if (is_up_front_neighbour)
5240  {
5241  // Trees_pt[i]->neighbour_pt(UF)=Trees_pt[j];
5242  octree_root_i_pt->add_edge_neighbour_pt(Trees_pt[j], UF);
5243  }
5244  }
5245  }
5246  }
5247  }
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
@ DF
Definition: octree.h:67
@ RD
Definition: octree.h:62
@ RB
Definition: octree.h:58
@ RU
Definition: octree.h:64
@ LF
Definition: octree.h:65
@ LD
Definition: octree.h:61
@ RF
Definition: octree.h:66
@ LU
Definition: octree.h:63
@ DB
Definition: octree.h:59
@ UB
Definition: octree.h:60
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References oomph::OcTreeRoot::add_edge_neighbour_pt(), D, oomph::OcTreeNames::DB, oomph::OcTreeNames::DF, oomph::OcTreeNames::F, i, j, L, oomph::OcTreeNames::LB, oomph::OcTreeNames::LD, oomph::OcTreeNames::LF, oomph::OcTreeNames::LU, n, oomph::TreeForest::ntree(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, R, oomph::OcTreeNames::RB, oomph::OcTreeNames::RD, oomph::OcTreeNames::RF, oomph::OcTreeNames::RU, oomph::TreeForest::Trees_pt, RachelsAdvectionDiffusion::U, oomph::OcTreeNames::UB, and oomph::OcTreeNames::UF.

Referenced by OcTreeForest().

◆ oc_edge_neigh_pt()

Vector<TreeRoot*> oomph::OcTreeForest::oc_edge_neigh_pt ( const unsigned i,
const int direction 
)
inline

Given the number i of the root octree in this forest, return the vector of pointers to the true edge neighbours in the specified (edge) direction.

1003  {
1004  // Note: paranoia check is done in edge_neighbour_pt
1005  return dynamic_cast<OcTreeRoot*>(Trees_pt[i])
1006  ->edge_neighbour_pt(direction);
1007  }

References oomph::OcTreeRoot::edge_neighbour_pt(), and i.

Referenced by construct_up_right_equivalents().

◆ oc_face_neigh_pt()

OcTreeRoot* oomph::OcTreeForest::oc_face_neigh_pt ( const unsigned i,
const int direction 
)
inline

Given the number i of the root octree in this forest, return pointer to its face neighbour in the specified direction. NULL if neighbour doesn't exist. (This does the dynamic cast from a TreeRoot to a OcTreeRoot internally).

983  {
984 #ifdef PARANOID
985  using namespace OcTreeNames;
986  if ((direction != U) && (direction != D) && (direction != F) &&
987  (direction != B) && (direction != L) && (direction != R))
988  {
989  std::ostringstream error_stream;
990  error_stream << "Wrong edge_direction: "
991  << OcTree::Direct_string[direction] << std::endl;
992  throw OomphLibError(
993  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
994  }
995 #endif
996  return dynamic_cast<OcTreeRoot*>(Trees_pt[i]->neighbour_pt(direction));
997  }
static Vector< std::string > Direct_string
Translate (enumerated) directions into strings.
Definition: octree.h:329
@ D
Definition: octree.h:71
@ U
Definition: octree.h:72

References oomph::OcTreeNames::D, oomph::OcTree::Direct_string, oomph::OcTreeNames::F, i, L, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, R, and oomph::OcTreeNames::U.

Referenced by construct_up_right_equivalents().

◆ octree_pt()

OcTreeRoot* oomph::OcTreeForest::octree_pt ( const unsigned i) const
inline

Return pointer to i-th OcTree in forest (Performs a dynamic cast from the TreeRoot to a OcTreeRoot).

974  {
975  return dynamic_cast<OcTreeRoot*>(Trees_pt[i]);
976  }

References i.

Referenced by construct_up_right_equivalents().

◆ open_hanging_node_files()

void oomph::OcTreeForest::open_hanging_node_files ( DocInfo doc_info,
Vector< std::ofstream * > &  output_stream 
)
virtual

Open output files that will store any hanging nodes in the forest and return a vector of the streams.

Open output files that will stored any hanging nodes that are

created in the mesh refinement process.

Implements oomph::TreeForest.

5896  {
5897  // In 3D, there will be six output files
5898  for (unsigned i = 0; i < 6; i++)
5899  {
5900  output_stream.push_back(new std::ofstream);
5901  }
5902 
5903  // If we are documenting the output, open the files
5904  if (doc_info.is_doc_enabled())
5905  {
5906  std::ostringstream fullname;
5907  fullname << doc_info.directory() << "/hang_nodes_u" << doc_info.number()
5908  << ".dat";
5909  output_stream[0]->open(fullname.str().c_str());
5910  fullname.str("");
5911  fullname << doc_info.directory() << "/hang_nodes_d" << doc_info.number()
5912  << ".dat";
5913  output_stream[1]->open(fullname.str().c_str());
5914  fullname.str("");
5915  fullname << doc_info.directory() << "/hang_nodes_l" << doc_info.number()
5916  << ".dat";
5917  output_stream[2]->open(fullname.str().c_str());
5918  fullname.str("");
5919  fullname << doc_info.directory() << "/hang_nodes_r" << doc_info.number()
5920  << ".dat";
5921  output_stream[3]->open(fullname.str().c_str());
5922  fullname.str("");
5923  fullname << doc_info.directory() << "/hang_nodes_b" << doc_info.number()
5924  << ".dat";
5925  output_stream[4]->open(fullname.str().c_str());
5926  fullname.str("");
5927  fullname << doc_info.directory() << "/hang_nodes_f" << doc_info.number()
5928  << ".dat";
5929  output_stream[5]->open(fullname.str().c_str());
5930  }
5931  }

References oomph::DocInfo::directory(), i, oomph::DocInfo::is_doc_enabled(), and oomph::DocInfo::number().

◆ operator=()

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

Broken assignment operator.

◆ self_test()

unsigned oomph::OcTreeForest::self_test ( )

Self test: Check neighbour finding routine.

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 Tree::Max_neighbour_finding_tolerance.

5679  {
5680  // Stick pointers to all nodes into Vector and number elements
5681  // in the process
5682  Vector<Tree*> all_nodes_pt;
5683  stick_all_tree_nodes_into_vector(all_nodes_pt);
5684  long int count = 0;
5685  unsigned long num_nodes = all_nodes_pt.size();
5686  for (unsigned long i = 0; i < num_nodes; i++)
5687  {
5688  all_nodes_pt[i]->object_pt()->set_number(++count);
5689  }
5690 
5691  // Check neighbours vertices and their opposite points
5692  std::ofstream neighbours_file;
5693  std::ofstream no_true_edge_file;
5694  std::ofstream neighbours_txt_file;
5695 
5696  double max_error_face = 0.0;
5698  all_nodes_pt, neighbours_file, neighbours_txt_file, max_error_face);
5699 
5700  double max_error_edge = 0.0;
5701  OcTree::doc_true_edge_neighbours(all_nodes_pt,
5702  neighbours_file,
5703  no_true_edge_file,
5704  neighbours_txt_file,
5705  max_error_edge);
5706 
5707  bool failed = false;
5708  if (max_error_face > OcTree::max_neighbour_finding_tolerance())
5709  {
5710  oomph_info << "\n\n Failed self_test() for OcTreeForest because of "
5711  "faces: Max. error "
5712  << max_error_face << std::endl
5713  << std::endl;
5714  failed = true;
5715  }
5716 
5717  if (max_error_edge > OcTree::max_neighbour_finding_tolerance())
5718  {
5719  oomph_info << "\n\n Failed self_test() for OcTreeForest because of "
5720  "edges: Max. error "
5721  << max_error_edge << std::endl
5722  << std::endl;
5723  failed = true;
5724  }
5725 
5726  double max_error = max_error_face;
5727  if (max_error_edge > max_error) max_error = max_error_edge;
5728 
5729  if (failed)
5730  {
5731  return 1;
5732  }
5733  else
5734  {
5735  oomph_info << "\nPassed self_test() for OcTreeForest: Max. error "
5736  << max_error << std::endl;
5737  return 0;
5738  }
5739  }

References oomph::OcTree::doc_face_neighbours(), oomph::OcTree::doc_true_edge_neighbours(), i, MeshRefinement::max_error, oomph::Tree::max_neighbour_finding_tolerance(), oomph::oomph_info, and oomph::TreeForest::stick_all_tree_nodes_into_vector().


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