binary_tree.cc
Go to the documentation of this file.
1// LIC// ====================================================================
2// LIC// This file forms part of oomph-lib, the object-oriented,
3// LIC// multi-physics finite-element library, available
4// LIC// at http://www.oomph-lib.org.
5// LIC//
6// LIC// Copyright (C) 2006-2025 Matthias Heil and Andrew Hazel
7// LIC//
8// LIC// This library is free software; you can redistribute it and/or
9// LIC// modify it under the terms of the GNU Lesser General Public
10// LIC// License as published by the Free Software Foundation; either
11// LIC// version 2.1 of the License, or (at your option) any later version.
12// LIC//
13// LIC// This library is distributed in the hope that it will be useful,
14// LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// LIC// Lesser General Public License for more details.
17// LIC//
18// LIC// You should have received a copy of the GNU Lesser General Public
19// LIC// License along with this library; if not, write to the Free Software
20// LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21// LIC// 02110-1301 USA.
22// LIC//
23// LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24// LIC//
25// LIC//====================================================================
26// Non-inline and non-templated functions for BinaryTree and BinaryTreeForest
27// classes
28
29// Config header
30#ifdef HAVE_CONFIG_H
31#include <oomph-lib-config.h>
32#endif
33
34#include <set>
35
36// oomph-lib headers
37#include "binary_tree.h"
39
40namespace oomph
41{
42 //========================================================================
43 /// Boolean indicating that static member data has been setup.
44 //========================================================================
46
47 //========================================================================
48 /// Colours for neighbours in various directions (static data).
49 //========================================================================
50 Vector<std::string> BinaryTree::Colour;
51
52 //========================================================================
53 /// S_base(direction): Initial value for coordinate s on the edge
54 /// indicated by direction (L/R) (static data).
55 //========================================================================
56 Vector<double> BinaryTree::S_base;
57
58 //========================================================================
59 /// Translate (enumerated) directions into strings (static data).
60 //========================================================================
61 Vector<std::string> BinaryTree::Direct_string;
62
63 //========================================================================
64 /// Get opposite edge, e.g. Reflect_edge[N]=S (static data)
65 //========================================================================
66 Vector<int> BinaryTree::Reflect_edge;
67
68 //========================================================================
69 /// Array of direction/segment adjacency scheme:
70 /// Is_adjacent(i_vertex,j_segment): Is vertex adjacent to segment?
71 /// (static data)
72 //========================================================================
73 DenseMatrix<bool> BinaryTree::Is_adjacent;
74
75 //========================================================================
76 /// Reflection scheme: Reflect(direction,segment): Get mirror of segment
77 /// in specified direction. E.g. Reflect(L,L)=R (static data)
78 //========================================================================
79 DenseMatrix<int> BinaryTree::Reflect;
80
81 //========================================================================
82 /// Set up the static data stored in the BinaryTree -- this needs to be
83 /// called before BinaryTrees can be used. Automatically called by
84 /// RefineableLineMesh constructor.
85 //========================================================================
87 {
88 using namespace BinaryTreeNames;
89
90#ifdef PARANOID
92 {
93 std::ostringstream error_stream;
94 error_stream << "Inconsistent enumeration! \n Tree::OMEGA="
95 << Tree::OMEGA << "\nBinaryTree::OMEGA=" << BinaryTree::OMEGA
96 << std::endl;
97 throw OomphLibError(
99 }
100#endif
101
102 // Set flag to indicate that static data has been setup
104
105 // Tecplot colours for neighbours in various directions
106 Colour.resize(27);
107
108 Colour[L] = "RED";
109 Colour[R] = "CYAN";
110 Colour[OMEGA] = "YELLOW";
111
112 // S_base(direction): Initial value for coordinate s on the
113 // edge indicated by direction (L/R)
114 S_base.resize(27);
115
116 S_base[L] = -1.0;
117 S_base[R] = 1.0;
118
119 // Translate (enumerated) directions into strings
120 Direct_string.resize(27);
121
122 Direct_string[L] = "L";
123 Direct_string[R] = "R";
124 Direct_string[OMEGA] = "OMEGA";
125
126 // Build direction/segment adjacency scheme:
127 // Is_adjacent(i_vertex,j_segment): Is vertex adjacent to segment?
128 Is_adjacent.resize(27, 27);
129
130 Is_adjacent(L, L) = true;
131 Is_adjacent(R, L) = false;
132 Is_adjacent(L, R) = false;
133 Is_adjacent(R, R) = true;
134
135 // Build reflection scheme: Reflect(direction,segment):
136 // Get mirror of segment in direction
137 Reflect.resize(27, 27);
138
139 Reflect(L, L) = R;
140 Reflect(R, L) = R;
141 Reflect(L, R) = L;
142 Reflect(R, R) = L;
143
144 // Get opposite edge, e.g. Reflect_edge(L)=R
145 Reflect_edge.resize(27);
146
147 Reflect_edge[L] = R;
148 Reflect_edge[R] = L;
149 }
150
151 //========================================================================
152 /// Return pointer to greater or equal-sized edge neighbour in specified
153 /// \c direction; also provide info regarding the relative size of the
154 /// neighbour:
155 /// - In the present binary tree, the left vertex is located at the local
156 /// coordinate s = -1. This point is located at the local coordinate
157 /// s = \c s_in_neighbour[0] in the neighbouring binary tree.
158 /// - We're looking for a neighbour in the specified \c direction. When
159 /// viewed from the neighbouring binary tree, the edge that separates
160 /// the present binary tree from its neighbour is the neighbour's
161 /// \c edge edge. Since in 1D there can be no rotation between the two
162 /// binary trees, this is a simple reflection. For instance, if we're
163 /// looking for a neighhbour in the \c L [eft] \c direction, \c edge
164 /// will be \c R [ight].
165 /// - \c diff_level <= 0 indicates the difference in refinement levels
166 /// between the two neighbours. If \c diff_level==0, the neighbour has
167 /// the same size as the current binary tree.
168 /// - \c in_neighbouring_tree returns true if we have had to flip to a
169 /// different root, even if that root is actually the same (as it can
170 /// be in periodic problems).
171 //========================================================================
174 int& edge,
175 int& diff_level,
176 bool& in_neighbouring_tree) const
177 {
178 using namespace BinaryTreeNames;
179
180#ifdef PARANOID
181 if ((direction != L) && (direction != R))
182 {
183 std::ostringstream error_stream;
184 error_stream << "Direction " << direction << " is not L or R"
185 << std::endl;
186
187 throw OomphLibError(
189 }
190#endif
191
192 // Initialise in_neighbouring tree to false. It will be set to true
193 // during the recursion if we do actually hop over into the neighbour
194 in_neighbouring_tree = false;
195
196 // Maximum level to which we're allowed to descend (we only want
197 // greater-or-equal-sized neighbours)
198 int max_level = Level;
199
200 // Current element has the following root:
202
203 // Initialise offset in local coordinate
204 double s_diff = 0;
205
206 // Initialise difference in level
207 diff_level = 0;
208
209 // Find neighbour
211 s_diff,
214 max_level,
216
218
219 // If neighbour exists...
220 if (neighb_pt != 0)
221 {
222 // What's the direction of the interfacial edge when viewed from within
223 // the neighbour element?
225
226 // What's the local coordinate s at which this edge is located in the
227 // neighbouring element?
229 }
230 return return_pt;
231 }
232
233 //========================================================================
234 /// Find `greater-or-equal-sized edge neighbour' in given direction (L/R).
235 ///
236 /// This is an auxiliary routine which allows neighbour finding in
237 /// adjacent binary trees. Needs to keep track of previous son types
238 /// and the maximum level to which search is performed.
239 ///
240 /// Parameters:
241 /// - direction (L/R): Direction in which neighbour has to be found.
242 /// - s_diff: Offset of left vertex from corresponding vertex in
243 /// neighbour. Note that this is input/output as it needs to be
244 /// incremented/decremented during the recursive calls to this function.
245 /// - edge: We're looking for the neighbour across our edge 'direction'
246 /// (L/R). When viewed from the neighbour, this edge is `edge' (L/R).
247 /// Since there is no relative rotation between neighbours this is a
248 /// mere reflection, e.g. direction=L --> edge=R etc.
249 /// - diff_level <= 0 indicates the difference in binary tree levels
250 /// between the current element and its neighbour.
251 /// - max_level is the maximum level to which the neighbour search is
252 /// allowed to proceed. This is again necessary because in a forest,
253 /// the neighbour search isn't based on pure recursion.
254 /// - orig_root_pt identifies the root node of the element whose
255 /// neighbour we're really trying to find by all these recursive calls.
256 //========================================================================
258 const int& direction,
259 double& s_diff,
260 int& diff_level,
262 int max_level,
263 BinaryTreeRoot* const& orig_root_pt) const
264 {
265 using namespace BinaryTreeNames;
266
267#ifdef PARANOID
268 if ((direction != L) && (direction != R))
269 {
270 std::ostringstream error_stream;
271 error_stream << "Direction " << direction << " is not L or R"
272 << std::endl;
273
274 throw OomphLibError(
276 }
277#endif
278
281
282 // STEP 1: Find the neighbour's father
283 // -------
284
285 // Does the element have a father?
286 if (Father_pt != 0)
287 {
288 // If the present segment (whose location inside its father element
289 // is specified by Son_type) is adjacent to the father's edge in the
290 // required direction, then its neighbour has a different father
291 // ---> we need to climb up the tree to the father and find his
292 // neighbour in the required direction. Note that this is the cunning
293 // recursive part. The returning may not stop until we hit the very
294 // top of the tree, when the element does NOT have a father.
296 {
298 direction,
299 s_diff,
302 max_level,
304 }
305 // If the present segment is not adjacent to the father's edge in the
306 // required direction, then the neighbour has the same father and is
307 // obtained by the appropriate reflection inside the father element.
308 // This will only be called if we have not left the original tree.
309 else
310 {
311 next_el_pt = dynamic_cast<BinaryTree*>(Father_pt);
312 }
313
314 // We're about to ascend one level
315 diff_level -= 1;
316
317 // Work out position of left corner of present edge in its father element
318 s_diff += pow(0.5, -diff_level);
319
320 // STEP 2: We have now located the neighbour's father and need to
321 // ------- find the appropriate son.
322
323 // Buffer cases where the neighbour (and hence its father) lie outside
324 // the boundary
325 if (next_el_pt != 0)
326 {
327 // If the father is a leaf then we can't descend to the same
328 // level as the present node ---> simply return the father himself
329 // as the (greater) neighbour. Same applies if we are about to
330 // descend lower than the max_level (in a neighbouring tree).
331 if ((next_el_pt->Son_pt.size() == 0) ||
332 (next_el_pt->Level > max_level - 1))
333 {
335 }
336 // We have located the neighbour's father: The position of the
337 // neighbour is obtained by `reflecting' the position of the
338 // node itself. We know exactly how to reflect because we know which
339 // son type we are and we have the pointer to the neighbour's father.
340 else
341 {
343
344 // The next element in the tree is the appropriate son of the
345 // neighbour's father
347 dynamic_cast<BinaryTree*>(next_el_pt->Son_pt[son_segment]);
348
349 // Work out position of left corner of present edge in next
350 // higher element
351 s_diff -= pow(0.5, -diff_level);
352
353 // We have just descended one level
354 diff_level += 1;
355 }
356 }
357 // The neighbour's father lies outside the boundary --> the neighbour
358 // itself does too --> return NULL
359 else
360 {
361 return_el_pt = 0;
362 }
363 }
364 // Element does not have a father --> check if it has a neighbouring
365 // tree in the appropriate direction
366 else
367 {
368 // Find neighbouring root
369 if (Root_pt->neighbour_pt(direction) != 0)
370 {
371 // In this case we have moved to a neighbour, so set the flag
375 }
376 // No neighbouring tree, so there really is no neighbour --> return NULL
377 else
378 {
379 return_el_pt = 0;
380 }
381 }
382
383 return return_el_pt;
384 }
385
386 //========================================================================
387 /// Self-test: Check neighbour finding routine. For each element in the
388 /// tree and for each vertex, determine the distance between the vertex
389 /// and its position in the neighbour. If the difference is less than
390 /// Tree::Max_neighbour_finding_tolerance return success (0), otherwise
391 /// failure (1).
392 //========================================================================
394 {
395 // Stick pointers to all nodes into Vector and number elements
396 // in the process
399 long int count = 0;
400 unsigned long num_nodes = all_nodes_pt.size();
401 for (unsigned long i = 0; i < num_nodes; i++)
402 {
403 all_nodes_pt[i]->object_pt()->set_number(++count);
404 }
405
406 // Check neighbours (distance between hanging nodes) -- don't print
407 // (keep output streams closed)
408 double max_error = 0.0;
409 std::ofstream neighbours_file;
410 std::ofstream neighbours_txt_file;
413
414 if (max_error > Max_neighbour_finding_tolerance)
415 {
416 oomph_info << "\n \n Failed self_test() for BinaryTree: Max. error "
417 << max_error << std::endl
418 << std::endl;
419 return 1;
420 }
421 else
422 {
423 oomph_info << "\n \n Passed self_test() for BinaryTree: Max. error "
424 << max_error << std::endl
425 << std::endl;
426 return 0;
427 }
428 }
429
430
431 //========================================================================
432 /// Constructor for BinaryTreeForest:
433 ///
434 /// Pass:
435 /// - trees_pt[], the Vector of pointers to the constituent trees
436 /// (BinaryTreeRoot objects)
437 //========================================================================
440 {
441#ifdef LEAK_CHECK
442 LeakCheckNames::BinaryTreeForest_build += 1;
443#endif
444
445 using namespace BinaryTreeNames;
446
447 // Set up the neighbours
449 }
450
451 //========================================================================
452 /// Set up the neighbour lookup schemes for all constituent binary trees.
453 //========================================================================
455 {
456 using namespace BinaryTreeNames;
457
458 unsigned numtrees = ntree();
459 unsigned n = 0; // to store nnode1d
460 if (numtrees > 0)
461 {
462 n = Trees_pt[0]->object_pt()->nnode_1d();
463 }
464 else
465 {
466 throw OomphLibError(
467 "Trying to setup the neighbour scheme for an empty forest\n",
470 }
471
472 // Number of vertex nodes: 2
473 unsigned n_vertex_node = 2;
474
475 // Find connected trees by identifying those whose associated elements
476 // share a common vertex node
477 std::map<Node*, std::set<unsigned>> tree_assoc_with_vertex_node;
478
479 // Loop over all trees
480 for (unsigned i = 0; i < numtrees; i++)
481 {
482 // Loop over the vertex nodes of the associated element
483 for (unsigned j = 0; j < n_vertex_node; j++)
484 {
485 Node* nod_pt = dynamic_cast<LineElementBase*>(Trees_pt[i]->object_pt())
486 ->vertex_node_pt(j);
488 }
489 }
490
491 // For each tree we store a set of neighbouring trees
492 // i.e. trees that share a node
494
495 // Loop over vertex nodes
496 for (std::map<Node*, std::set<unsigned>>::iterator it =
499 it++)
500 {
501 // Loop over connected elements twice
502 for (std::set<unsigned>::iterator it_el1 = it->second.begin();
503 it_el1 != it->second.end();
504 it_el1++)
505 {
506 unsigned i = (*it_el1);
507 for (std::set<unsigned>::iterator it_el2 = it->second.begin();
508 it_el2 != it->second.end();
509 it_el2++)
510 {
511 unsigned j = (*it_el2);
512 // These two elements are connected
513 if (i != j)
514 {
515 neighb_tree[i].insert(j);
516 }
517 }
518 }
519 }
520
521 // Loop over all trees
522 for (unsigned i = 0; i < numtrees; i++)
523 {
524 // Loop over their neighbours
525 for (std::set<unsigned>::iterator it = neighb_tree[i].begin();
526 it != neighb_tree[i].end();
527 it++)
528 {
529 unsigned j = (*it);
530
531 // is it the left-hand neighbour?
532 bool is_L_neighbour = Trees_pt[j]->object_pt()->get_node_number(
533 Trees_pt[i]->object_pt()->node_pt(0)) != -1;
534
535 // is it the right-hand neighbour?
536 bool is_R_neighbour = Trees_pt[j]->object_pt()->get_node_number(
537 Trees_pt[i]->object_pt()->node_pt(n - 1)) != -1;
538
539 if (is_L_neighbour) Trees_pt[i]->neighbour_pt(L) = Trees_pt[j];
540 if (is_R_neighbour) Trees_pt[i]->neighbour_pt(R) = Trees_pt[j];
541 }
542 } // End of loop over all trees
543 }
544
545 //========================================================================
546 /// Document and check all the neighbours in all the nodes in the forest.
547 //========================================================================
549 {
550 // Create Vector of elements
552 this->stick_all_tree_nodes_into_vector(all_tree_nodes_pt);
553
554 // Create storage for information files
555 std::ofstream neigh_file;
556 std::ofstream neigh_txt_file;
557
558 // If we are documenting the results, then open the files
559 if (doc_info.is_doc_enabled())
560 {
561 std::ostringstream fullname;
562 fullname << doc_info.directory() << "/neighbours" << doc_info.number()
563 << ".dat";
564 oomph_info << "opened " << fullname.str() << " to doc neighbours"
565 << std::endl;
566 neigh_file.open(fullname.str().c_str());
567 fullname.str("");
568 fullname << doc_info.directory() << "/neighbours" << doc_info.number()
569 << ".txt";
570 oomph_info << "opened " << fullname.str() << " to doc neighbours"
571 << std::endl;
572 neigh_txt_file.open(fullname.str().c_str());
573 }
574
575 // Call the standard documentation function
576 double max_error = 0.0;
579
580 // If the error is too large, complain
582 {
583 std::ostringstream error_stream;
584 error_stream << "Max. error in binary tree neighbour finding: "
585 << max_error << " is too big" << std::endl;
587 << "i.e. bigger than Tree::max_neighbour_finding_tolerance()="
589
590 // Close the files if they were opened
591 if (doc_info.is_doc_enabled())
592 {
593 neigh_file.close();
594 neigh_txt_file.close();
595 }
596
597 throw OomphLibError(
599 }
600 else
601 {
602 oomph_info << "Max. error in binary tree neighbour finding: " << max_error
603 << " is OK" << std::endl;
605 << "i.e. less than BinaryTree::max_neighbour_finding_tolerance()="
607 }
608
609 // Close the files if they were opened
610 if (doc_info.is_doc_enabled())
611 {
612 neigh_file.close();
613 neigh_txt_file.close();
614 }
615 }
616
617 //========================================================================
618 /// Self test: Check neighbour finding routine. For each element in the
619 /// tree and for each vertex, determine the distance between the vertex
620 /// and its position in the neighbour. If the difference is less than
621 /// Tree::Max_neighbour_finding_tolerance return success (0), otherwise
622 /// failure (1).
623 //========================================================================
625 {
626 // Stick pointers to all nodes into Vector and number elements
627 // in the process
630 long int count = 0;
631 unsigned long num_nodes = all_forest_nodes_pt.size();
632 for (unsigned long i = 0; i < num_nodes; i++)
633 {
634 all_forest_nodes_pt[i]->object_pt()->set_number(++count);
635 }
636
637 // Check neighbours (distance between hanging nodes) -- don't print
638 // (keep output streams closed)
639 double max_error = 0.0;
640 std::ofstream neighbours_file;
641 std::ofstream neighbours_txt_file;
645 {
646 oomph_info << "\n \n Failed self_test() for BinaryTree: Max. error "
647 << max_error << std::endl
648 << std::endl;
649 return 1;
650 }
651 else
652 {
653 oomph_info << "\n \n Passed self_test() for BinaryTree: Max. error "
654 << max_error << std::endl
655 << std::endl;
656 return 0;
657 }
658 }
659
660 //========================================================================
661 /// Doc/check all neighbours of binary tree ("nodes") contained in the
662 /// Vector forest_node_pt. Output into neighbours_file which can be viewed
663 /// from tecplot with BinaryTreeNeighbours.mcr. Neighbour info and errors
664 /// are displayed on neighbours_txt_file. Finally, compute the maximum
665 /// error between vertices when viewed from neighbouring element. Output
666 /// is suppressed if the output streams are closed.
667 //========================================================================
669 std::ofstream& neighbours_file,
670 std::ofstream& neighbours_txt_file,
671 double& max_error)
672 {
673 using namespace BinaryTreeNames;
674
675 int diff_level;
676 double s_diff;
678 int edge = OMEGA;
679
680 Vector<double> s(1);
681 Vector<double> x(1);
683
685
688
689 // Initialise error in vertex positions
690 max_error = 0.0;
691
692 // Loop over all elements to assign numbers for plotting
693 // -----------------------------------------------------
694 unsigned long num_nodes = forest_nodes_pt.size();
695 for (unsigned long i = 0; i < num_nodes; i++)
696 {
697 // Set number
698 forest_nodes_pt[i]->object_pt()->set_number(i);
699 }
700
701 // Loop over all elements for checks
702 // ---------------------------------
703 for (unsigned long i = 0; i < num_nodes; i++)
704 {
705 // Doc the element itself
706 BinaryTree* el_pt = dynamic_cast<BinaryTree*>(forest_nodes_pt[i]);
707
708 // If the object is incomplete, complain
709 if (el_pt->object_pt()->nodes_built())
710 {
711 // Print it
712 if (neighbours_file.is_open())
713 {
714 dynamic_cast<RefineableQElement<1>*>(el_pt->object_pt())
715 ->output_corners(neighbours_file, "BLACK");
716 }
717
718 // Loop over directions to find neighbours
719 // ---------------------------------------
720 for (int direction = L; direction <= R; direction++)
721 {
722 // Initialise difference in levels and coordinate offset
723 diff_level = 0;
724 s_diff = 0.0;
725
726 // Find greater-or-equal-sized neighbour...
727 BinaryTree* neighb_pt = el_pt->gteq_edge_neighbour(
729
730 // If neighbour exist and nodes are created: Doc it
731 if ((neighb_pt != 0) && (neighb_pt->object_pt()->nodes_built()))
732 {
733 // Doc neighbour stats
734 if (neighbours_txt_file.is_open())
735 {
737 << Direct_string[direction] << " neighbour of "
738 << el_pt->object_pt()->number() << " is "
739 << neighb_pt->object_pt()->number() << " diff_level "
740 << diff_level << " s_diff " << s_diff
741 << " inside neighbour the edge is " << Direct_string[edge]
742 << std::endl
743 << std::endl;
744 }
745
746 // Plot neighbour in the appropriate colour
747 if (neighbours_file.is_open())
748 {
749 dynamic_cast<RefineableQElement<1>*>(neighb_pt->object_pt())
750 ->output_corners(neighbours_file, Colour[direction]);
751 }
752
753 // Check that local coordinates in the larger element (obtained
754 // via s_diff) lead to the same spatial point as the node vertices
755 // in the current element
756 {
757 if (neighbours_file.is_open())
758 {
759 neighbours_file << "ZONE I=1 \n";
760 }
761
762 // Left vertex:
763 // ------------
764
765 // Get coordinates in large (neighbour) element
766 s[0] = s_in_neighbour[0];
767 neighb_pt->object_pt()->get_x(s, x_large);
768
769 // Get coordinates in small element
770 Vector<double> s(1);
771 s[0] = S_base[direction];
772 el_pt->object_pt()->get_x(s, x_small);
773
774 // Need to exclude periodic nodes from this check. There can
775 // only be periodic nodes if we have moved into the neighbour
776 bool is_periodic = false;
778 {
779 // Is the node periodic?
781 el_pt->root_pt()->is_neighbour_periodic(direction);
782 }
783
784 double error = 0.0;
785 // Only bother to calculate the error if the node is NOT periodic
786 if (is_periodic == false)
787 {
788 error += pow(x_small[0] - x_large[0], 2);
789 }
790
791 // Take the root of the square error
792 error = sqrt(error);
793 if (neighbours_txt_file.is_open())
794 {
795 neighbours_txt_file << "Error (1) " << error << std::endl;
796 }
797
798 if (std::fabs(error) > max_error)
799 {
800 max_error = std::fabs(error);
801 }
802
803 if (neighbours_file.is_open())
804 {
805 neighbours_file << x_large[0] << " 0 \n";
806 }
807
808 // Right vertex:
809 // -------------
810
811 // Get coordinates in large (neighbour) element
812 s[0] = s_in_neighbour[0];
813 neighb_pt->object_pt()->get_x(s, x_large);
814
815 // Get coordinates in small element
816 s[0] = S_base[direction];
817 el_pt->object_pt()->get_x(s, x_small);
818
819 error = 0.0;
820 // Only do this if we are NOT periodic
821 if (is_periodic == false)
822 {
823 error += pow(x_small[0] - x_large[0], 2);
824 }
825 // Take the root of the square error
826 error = sqrt(error);
827
828 // error =
829 // sqrt(pow(x_small[0]-x_large[0],2)+pow(x_small[1]-x_large[1],2));
830 if (neighbours_txt_file.is_open())
831 {
832 neighbours_txt_file << "Error (2) " << error << std::endl;
833 }
834
835 if (std::fabs(error) > max_error)
836 {
837 max_error = std::fabs(error);
838 }
839
840 if (neighbours_file.is_open())
841 {
842 neighbours_file << x_large[0] << " 0 \n";
843 }
844 }
845 // else
846 // {
847 // // No neighbour: write dummy zone so tecplot can find
848 // four
849 // // neighbours for every element
850 // if (neighbours_file.is_open())
851 // {
852 // neighbours_file << "ZONE I=1 \n";
853 // neighbours_file << "-0.05 -0.05 0 \n";
854 // neighbours_file << "-0.05 -0.05 0 \n";
855 // }
856 // }
857 }
858 // If neighbour does not exist: Insert blank zones into file
859 // so that tecplot can find four neighbours for every element
860 else
861 {
862 if (neighbours_file.is_open())
863 {
864 neighbours_file << "ZONE \n 0.00 0 \n";
865 neighbours_file << "ZONE I=1 \n";
866 neighbours_file << "-0.05 0 \n";
867 neighbours_file << "-0.05 0 \n";
868 }
869 }
870 }
871 } // End of case when element can be documented
872 }
873 }
874
875} // namespace oomph
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
void find_neighbours()
Construct the neighbour lookup scheme.
BinaryTreeForest()
Default constructor (empty and broken)
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...
unsigned self_test()
Self-test: Check all neighbours. Return success (0) if the maximum distance between corresponding poi...
BinaryTreeRoot is a BinaryTree that forms the root of a (recursive) binary tree. The "root node" is s...
BinaryTree class: Recursively defined, generalised binary tree.
Definition binary_tree.h:92
static Vector< double > S_base
S_base(direction): Initial value for coordinate s on the edge indicated by direction (L/R)
static Vector< std::string > Colour
Colours for neighbours in various directions.
static Vector< std::string > Direct_string
Translate (enumerated) directions into strings.
static void setup_static_data()
Set up the static data, reflection schemes, etc.
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 binary tree (nodes) contained in the Vector forest_node_pt....
static bool Static_data_has_been_setup
Boolean indicating that static member data has been setup.
static DenseMatrix< int > Reflect
Reflection scheme: Reflect(direction,segment): Get mirror of segment in specified direction....
BinaryTree * gteq_edge_neighbour(const int &direction, Vector< double > &s_in_neighbour, 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 maximum distance between corresponding poi...
static DenseMatrix< bool > Is_adjacent
Array of direction/segment adjacency scheme: Is_adjacent(i_vertex,j_segment): Is vertex adjacent to s...
static Vector< int > Reflect_edge
Get opposite edge, e.g. Reflect_edge[L]=R.
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.
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
Definition elements.cc:4320
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...
Definition elements.h:1889
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
Definition elements.h:2222
int get_node_number(Node *const &node_pt) const
Return the number of the node *node_pt if this node is in the element, else return -1;.
Definition elements.cc:3844
Base class for all line elements.
Definition Qelements.h:466
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition nodes.h:906
An OomphLibError object which should be thrown when an run-time error is encountered....
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
A TreeForest consists of a collection of TreeRoots. Each member tree can have neighbours in various e...
Definition tree.h:409
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
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
TreeRoot *& neighbour_pt(const int &direction)
Return the pointer to the neighbouring TreeRoots in specified direction. Returns NULL if there's no n...
Definition tree.h:357
Tree * Father_pt
Pointer to the Father of the Tree.
Definition tree.h:296
void stick_all_tree_nodes_into_vector(Vector< Tree * > &)
Traverse and stick pointers to all "nodes" into Vector.
Definition tree.cc:277
TreeRoot * Root_pt
Pointer to the root of the tree.
Definition tree.h:292
int Son_type
Son type (e.g. SW/SE/NW/NE in a quadtree)
Definition tree.h:305
static double & max_neighbour_finding_tolerance()
Max. allowed discrepancy in neighbour finding routine (distance between points when identified from t...
Definition tree.h:255
int Level
Level of the Tree (level 0 = root)
Definition tree.h:302
static const int OMEGA
Default value for an unassigned neighbour.
Definition tree.h:262
static double Max_neighbour_finding_tolerance
Max. allowed discrepancy in neighbour finding routine (distance between points when identified from t...
Definition tree.h:313
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...