KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
octree_binary.h
Go to the documentation of this file.
1 
2 // | / |
3 // ' / __| _` | __| _ \ __|
4 // . \ | ( | | ( |\__ `
5 // _|\_\_| \__,_|\__|\___/ ____/
6 // Multi-Physics
7 //
8 // License: BSD License
9 // Kratos default license: kratos/license.txt
10 //
11 // Main authors: Abel Coll
12 // Pooyan Dadvand
13 //
14 
15 #pragma once
16 
17 // System includes
18 #include <string>
19 #include <iostream>
20 
21 // External includes
22 
23 // Project includes
24 #include "includes/define.h"
25 #include "geometries/geometry.h"
26 #include "includes/node.h"
27 
28 #include "octree_binary_cell.h"
29 
30 #define KRATOS_WATCH_3(name) std::cout << #name << " : " << name[0] << ", " << name[1] << ", " << name[2] << std::endl;
31 
32 namespace Kratos {
35 
38 
42 
46 
50 
54 
56 
59  template <class TCellType>
60  class OctreeBinary {
61  public:
64 
67 
68  typedef TCellType cell_type;
69 
70  typedef typename cell_type::key_type key_type;
71 
72  typedef typename cell_type::configuration_type configuration_type;
73 
74  typedef double coordinate_type;
75 
76  typedef Node NodeType;
77 
79 
80  static constexpr std::size_t CHILDREN_NUMBER = cell_type::CHILDREN_NUMBER;
81  static constexpr std::size_t DIMENSION = cell_type::DIMENSION;
82  static constexpr std::size_t MAX_LEVEL = cell_type::MAX_LEVEL;
83  static constexpr std::size_t ROOT_LEVEL = cell_type::ROOT_LEVEL;
84  static constexpr std::size_t MIN_LEVEL = cell_type::MIN_LEVEL; // must be greater iqual to 2
85 
89 
91 
92  OctreeBinary() : root_(new cell_type), number_of_cells_(CHILDREN_NUMBER + 1), number_of_leaves_(1), levels_(0) {
93 
94  for(unsigned int i = 0 ; i < DIMENSION ; i++){
95  mScaleFactor[i] = 1.00;
96  mOffset[i] = 0.00;
97  }
98  }
99 
100  OctreeBinary(const double* NewScaleFactor, const double* NewOffset) : root_(new cell_type), number_of_cells_(CHILDREN_NUMBER + 1), number_of_leaves_(1), levels_(0) {
101  for(unsigned int i = 0 ; i < DIMENSION ; i++){
102  mScaleFactor[i] = NewScaleFactor[i];
103  mOffset[i] = NewOffset[i];
104  }
105  }
106 
108 
109  virtual ~OctreeBinary() {
110  delete root_;
111  }
112 
116 
117 
121 
122  void SetBoundingBox(const coordinate_type * Low, const coordinate_type * High)
123  {
124  for(unsigned int i = 0 ; i < DIMENSION ; i++){
125  mScaleFactor[i] = 1/(High[i] - Low[i]);
126  mOffset[i] = -Low[i];
127  }
128  }
129 
130  double CalcSizeNormalized(const cell_type* cell) const {
131  const double scale = 1.00 / (1 << ROOT_LEVEL);
132 
133  return (1 << cell->GetLevel()) * scale; // I'm doing it in this way to avoid division
134  }
135 
137  const double scale = 1.00 / (1 << ROOT_LEVEL);
138  return (1 << MIN_LEVEL) * scale; // I'm doing it in this way to avoid division
139  }
140 
141  void NormalizeCoordinates(coordinate_type* Coordinates) const
142  {
143  for(unsigned int i = 0 ; i < DIMENSION ; i++){
144  Coordinates[i] += mOffset[i];
145  Coordinates[i] *= mScaleFactor[i];
146  }
147  }
148 
149  void NormalizeCoordinates(const coordinate_type * Coordinates, coordinate_type * NormalizedCoordinates) const
150  {
151  for(int i = 0 ; i < 3 ; i++)
152  {
153  NormalizedCoordinates[i] = Coordinates[i] + mOffset[i];
154  NormalizedCoordinates[i] *= mScaleFactor[i];
155  }
156  }
157 
158  void CalculateCoordinateNormalized(const key_type key, coordinate_type& NormalizedCoordinate) const {
159  const double scale = 1.00 / (1 << ROOT_LEVEL);
160  NormalizedCoordinate = static_cast<double>(key * scale);
161  }
162 
163  void CalculateCoordinatesNormalized(const key_type* keys, coordinate_type * NormalizedCoordinates) const {
164  const double scale = 1.00 / (1 << ROOT_LEVEL);
165  for(unsigned int i = 0 ; i < DIMENSION ; i++)
166  NormalizedCoordinates[i] = static_cast<double>(keys[i] * scale);
167  }
168 
169  void CalculateCoordinates(key_type* keys, coordinate_type * ResultCoordinates) const {
170  const double scale = 1.00 / (1 << ROOT_LEVEL);
171  for(unsigned int i = 0 ; i < DIMENSION ; i++)
172  ResultCoordinates[i] = (static_cast<double>(keys[i] * scale) / mScaleFactor[i]) - mOffset[i];
173  }
174 
175  void ScaleBackToOriginalCoordinate(coordinate_type * ThisCoordinates) const
176  {
177  for(unsigned int i = 0 ; i < DIMENSION ; i++){
178  ThisCoordinates[i] /= mScaleFactor[i];
179  ThisCoordinates[i] -= mOffset[i];
180  }
181 
182  }
183 
184  void ScaleBackToOriginalCoordinate(const coordinate_type * ThisCoordinates, coordinate_type * ResultCoordinates) const
185  {
186  for(unsigned int i = 0 ; i < DIMENSION ; i++){
187  ResultCoordinates[i] = ThisCoordinates[i] / mScaleFactor[i];
188  ResultCoordinates[i] -= mOffset[i];
189  }
190 
191  }
192 
193  //pooyan. uncomment this when needed
194  //key_type CalcKey(coordinate_type coordinate) const {
195  // //pooyan. NEED TO SCALE COORDINATE!!!
196  // return CalcKeyNormalized(coordinate);
197  //}
198 
200  assert(coordinate>=0.); assert(coordinate<=1.);
201  return static_cast<key_type> ((1 << ROOT_LEVEL) * coordinate);
202  }
203 
205  key_type x_key = CalcKeyNormalized(point[0]);
206  key_type y_key = CalcKeyNormalized(point[1]);
207  key_type z_key = CalcKeyNormalized(point[2]);
208 
209  cell_type* cell = root_;
210 
211  for (std::size_t i = ROOT_LEVEL; i > MIN_LEVEL; i--) {
212  if (cell->IsLeaf()) {
213  SubdivideCell(cell);
214  }
215  cell = cell->pGetChild(x_key, y_key, z_key);
216  }
217 
218  }
219 
220  void Insert(coordinate_type* point) {
221  coordinate_type normalized_point[3];
222  NormalizeCoordinates(point, normalized_point);
223  key_type x_key = CalcKeyNormalized(normalized_point[0]);
224  key_type y_key = CalcKeyNormalized(normalized_point[1]);
225  key_type z_key = CalcKeyNormalized(normalized_point[2]);
226 
227  cell_type* cell = root_;
228 
229  for (std::size_t i = ROOT_LEVEL; i > MIN_LEVEL; i--) {
230  if (cell->IsLeaf()) {
231  SubdivideCell(cell);
232  }
233  cell = cell->pGetChild(x_key, y_key, z_key);
234  }
235 
236  }
237 
238  bool CheckConstrain2To1() const{
239  //POOYAN. This function must return true if the octree is balanced (constrained2:1) and false if not.
240  return true;
241  }
242 
243  void Constrain2To1() {
244  std::vector<cell_type*> leaves;
245  std::vector<cell_type*> next_leaves;
246 
247  //when the function will be at upper level (in mesher instead of octree) this vector (leaves) should be passed and copied instead of recomputed
248  GetAllLeavesVector(leaves);
249 
250  for (char i_level = MIN_LEVEL; i_level < ROOT_LEVEL - 1; i_level++) {
251  for (std::size_t i_cell = 0; i_cell < leaves.size(); i_cell++) {
252  cell_type* current_leaf = leaves[i_cell];
253  if (current_leaf->GetLevel() == i_level) {
254  key_type neighbour_key[3];
255  //18 is the number of neighbours counting faces and edges of the cell
256  for (int i_direction = 0; i_direction < 18; i_direction++) {
257  if (current_leaf->GetNeighbourKey(i_direction, neighbour_key)) {
258  cell_type* neighbour_cell = pGetCell(neighbour_key);
259  if (neighbour_cell->GetLevel() > i_level + 1) {
260  cell_type* temp_neighbour_cell = neighbour_cell;
261  for (char j_level = neighbour_cell->GetLevel(); j_level > i_level + 1; j_level--) {
262  SubdivideCell(temp_neighbour_cell);
263  temp_neighbour_cell->TransferObjectsToSonsNormalized();
264  std::size_t child_index = temp_neighbour_cell->GetChildIndex(neighbour_key[0], neighbour_key[1], neighbour_key[2]);
265  for (std::size_t j = 0; j < CHILDREN_NUMBER; j++) {
266  if (j != child_index) {
267  next_leaves.push_back(temp_neighbour_cell->GetChildren() + j);
268  }
269  }
270  temp_neighbour_cell = temp_neighbour_cell->GetChildren() + child_index;
271  if (j_level == neighbour_cell->GetLevel() - 1) // the last loop we add all the child as leaf
272  next_leaves.push_back(temp_neighbour_cell);
273  }
274  }
275  }
276  }
277  } else if (current_leaf->IsLeaf()) { // becuase it may be divided
278  next_leaves.push_back(current_leaf);
279  }
280  }
281  leaves.swap(next_leaves);
282  next_leaves.clear();
283  }
284  }
285 
287  std::vector<cell_type*> leaves;
288  std::vector<cell_type*> next_leaves;
289 
290  GetAllLeavesVector(leaves);
291 
292  for (char i_level = MIN_LEVEL; i_level < ROOT_LEVEL - 1; i_level++) {
293  for (int i_direction = 0; i_direction < 18; i_direction++) {
294  for (std::size_t i_cell = 0; i_cell < leaves.size(); i_cell++) {
295  cell_type* current_leaf = leaves[i_cell];
296  if (current_leaf->GetLevel() == i_level) {
297  key_type neighbour_key[3];
298  if (current_leaf->GetNeighbourKey(i_direction, neighbour_key)) {
299  cell_type* neighbour_cell = pGetCell(neighbour_key);
300  if (neighbour_cell->GetLevel() > i_level + 1) {
301  cell_type* temp_neighbour_cell = neighbour_cell;
302  for (char j_level = neighbour_cell->GetLevel(); j_level > i_level + 1; j_level--) {
303  SubdivideCell(temp_neighbour_cell);
304 
305  std::size_t child_index = temp_neighbour_cell->GetChildIndex(neighbour_key[0], neighbour_key[1], neighbour_key[2]);
306  for (std::size_t j = 0; j < CHILDREN_NUMBER; j++) {
307  if (j != child_index) {
308  next_leaves.push_back(temp_neighbour_cell->GetChildren() + j);
309  }
310  }
311  temp_neighbour_cell = temp_neighbour_cell->GetChildren() + child_index;
312  if (j_level == neighbour_cell->GetLevel() - 1) // the last loop we add all the child as leaf
313  next_leaves.push_back(temp_neighbour_cell);
314  }
315  }
316  }
317  } else if (i_direction == 0) {
318  if (current_leaf->IsLeaf()) { // becuase it may be divided
319  next_leaves.push_back(current_leaf);
320  }
321  }
322  }
323  }
324  leaves.swap(next_leaves);
325  next_leaves.clear();
326  KRATOS_WATCH(leaves.size())
327  }
328  KRATOS_WATCH(number_of_leaves_);
329  }
330 
331  void GetLeavesInBoundingBoxNormalized(const double* coord1, const double* coord2,
332  std::vector<cell_type*>& leaves) const
333  {
334  key_type min_x_key = CalcKeyNormalized(coord1[0]);
335  key_type min_y_key = CalcKeyNormalized(coord1[1]);
336  key_type min_z_key = CalcKeyNormalized(coord1[2]);
337 
338  key_type max_x_key = CalcKeyNormalized(coord2[0]);
339  key_type max_y_key = CalcKeyNormalized(coord2[1]);
340  key_type max_z_key = CalcKeyNormalized(coord2[2]);
341 
342  key_type delta_x = min_x_key^max_x_key;
343  key_type delta_y = min_y_key^max_y_key;
344  key_type delta_z = min_z_key^max_z_key;
345 
346  // finding the level of the cell containing the entire region
347  std::size_t min_level_1 = ROOT_LEVEL;
348  std::size_t min_level_2 = ROOT_LEVEL;
349  std::size_t min_level = ROOT_LEVEL;
350 
351  const std::size_t one = 1;
352  while (!(delta_x & (one << min_level_1)) && (min_level_1 > MIN_LEVEL)) min_level_1--;
353  while (!(delta_y & (one << min_level_2)) && (min_level_2 > min_level_1)) min_level_2--;
354  while (!(delta_z & (one << min_level)) && (min_level > min_level_2)) min_level--;
355  min_level++;
356 
357  cell_type* range_cell = root_;
358 
359  for (std::size_t i = ROOT_LEVEL; i > min_level; i--) {
360  if (range_cell->IsLeaf()) {
361  break;
362  }
363  range_cell = range_cell->pGetChild(min_x_key, min_y_key, min_z_key);
364 
365  }
366  // Now we have the cell (or leaf) containing the entire range and from now on we have to gather the leaves
367  std::vector<cell_type*> cells_stack;
368  cells_stack.push_back(range_cell);
369  while (!cells_stack.empty()) {
370  cell_type* cell = cells_stack.back();
371  cells_stack.pop_back();
372  if (cell->HasChildren()) {
373  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++){
374  //abel. to be optimized
375  cell_type* child=cell->pGetChild(i);
376 
377  double low[3];
378  double high[3];
379  child->GetMinPoint(low);
380  child->GetMaxPoint(high);
381  if (Collides(coord1, coord2, low, high))
382  cells_stack.push_back(cell->pGetChild(i));
383  }
384  } else
385  leaves.push_back(cell);
386  }
387 
388 
389  return;
390  }
391 
392 
393  bool Collides(const double* Low1, const double* High1, const double* Low2, const double* High2)
394  {
395  return (Low1[0] <= High2[0]) &&
396  (Low1[1] <= High2[1]) &&
397  (Low1[2] <= High2[2]) &&
398  (Low2[0] <= High1[0]) &&
399  (Low2[1] <= High1[1]) &&
400  (Low2[2] <= High1[2]);
401  }
402 
403 
404  int GetAllLeavesVector(std::vector<cell_type*>& all_leaves) const {
405  std::vector<cell_type*> cells_stack;
406  cells_stack.push_back(root_);
407  while (!cells_stack.empty()) {
408  cell_type* cell = cells_stack.back();
409  cells_stack.pop_back();
410  if (cell->HasChildren()) {
411  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++)
412  cells_stack.push_back(cell->pGetChild(i));
413  } else
414  all_leaves.push_back(cell);
415  }
416 
417  return 0;
418  }
419 
421  key_type keys[3];
422  keys[0] = CalcKeyNormalized(point[0]);
423  keys[1] = CalcKeyNormalized(point[1]);
424  keys[2] = CalcKeyNormalized(point[2]);
425 
426  return pGetCell(keys);
427  }
428 
430  cell_type* cell = root_;
431 
432  for (std::size_t i = 0; i < ROOT_LEVEL; i++) {
433  if (cell->IsLeaf()) {
434  return cell;
435  }
436  cell = cell->pGetChild(keys[0], keys[1], keys[2]);
437  }
438  return cell;
439  }
440 
441  cell_type * pGetCell(key_type* keys, std::size_t level) const {
442  cell_type* cell = root_;
443 
444  for (std::size_t i = ROOT_LEVEL; i > level; i--) {
445  if (cell->IsLeaf()) {
446  return cell;
447  }
448  cell = cell->pGetChild(keys[0], keys[1], keys[2]);
449  }
450  return cell;
451  }
452 
453  cell_type * pGetLeftCell(const cell_type * p_cell) {
454  key_type keys[3];
455  if (p_cell->GetLeftKey(keys)) {
456  return pGetCell(keys);
457  }
458  return NULL; // no neighbour
459  }
460 
461  cell_type * pGetLeftCell(cell_type* p_cell, std::size_t level) {
462  key_type keys[3];
463  if (p_cell->GetLeftKey(keys)) {
464  return pGetCell(keys, level);
465  }
466  return NULL; // no neighbour
467  }
468 
469  cell_type * pGetRightCell(const cell_type * p_cell) {
470  key_type keys[3];
471  if (p_cell->GetRightKey(keys)) {
472  return pGetCell(keys);
473  }
474  return NULL; // no neighbour
475  }
476 
477  cell_type * pGetRightCell(cell_type* p_cell, std::size_t level) {
478  key_type keys[3];
479  if (p_cell->GetRightKey(keys)) {
480  return pGetCell(keys, level);
481  }
482  return NULL; // no neighbour
483  }
484 
485  cell_type * pGetBackCell(const cell_type * p_cell) {
486  key_type keys[3];
487  if (p_cell->GetBackKey(keys)) {
488  return pGetCell(keys);
489  }
490  return NULL; // no neighbour
491  }
492 
493  cell_type * pGetBackCell(cell_type* p_cell, std::size_t level) {
494  key_type keys[3];
495  if (p_cell->GetBackKey(keys)) {
496  return pGetCell(keys, level);
497  }
498  return NULL; // no neighbour
499  }
500 
501  cell_type * pGetFrontCell(const cell_type * p_cell) {
502  key_type keys[3];
503  if (p_cell->GetFrontKey(keys)) {
504  return pGetCell(keys);
505  }
506  return NULL; // no neighbour
507  }
508 
509  cell_type * pGetFrontCell(cell_type* p_cell, std::size_t level) {
510  key_type keys[3];
511  if (p_cell->GetFrontKey(keys)) {
512  return pGetCell(keys, level);
513  }
514  return NULL; // no neighbour
515  }
516 
517  cell_type * pGetTopCell(const cell_type * p_cell) {
518  key_type keys[3];
519  if (p_cell->GetTopKey(keys)) {
520  return pGetCell(keys);
521  }
522  return NULL; // no neighbour
523  }
524 
525  cell_type * pGetTopCell(cell_type* p_cell, std::size_t level) {
526  key_type keys[3];
527  if (p_cell->GetTopKey(keys)) {
528  return pGetCell(keys, level);
529  }
530  return NULL; // no neighbour
531  }
532 
533  cell_type * pGetBottomCell(const cell_type * p_cell) {
534  key_type keys[3];
535  if (p_cell->GetBottomKey(keys)) {
536  return pGetCell(keys);
537  }
538  return NULL; // no neighbour
539  }
540 
541  cell_type * pGetBottomCell(cell_type* p_cell, std::size_t level) {
542  key_type keys[3];
543  if (p_cell->GetBottomKey(keys)) {
544  return pGetCell(keys, level);
545  }
546  return NULL; // no neighbour
547  }
548 
549  cell_type * pGetNeighbourCell(const cell_type* p_cell, std::size_t direction) {
550  key_type keys[3];
551 
552  if (p_cell->GetNeighbourKey(direction, keys)) {
553  return pGetCell(keys);
554  }
555  return NULL; // no neighbour
556  }
557 
558  cell_type * pGetNeighbourCell(cell_type* p_cell, std::size_t position, std::size_t direction) {
559  key_type keys[3];
560 
561  if (p_cell->GetNeighbourKey(position, direction, keys)) {
562  return pGetCell(keys);
563  }
564  return NULL; // no neighbour
565  }
566 
567  int SubdivideCell(cell_type* p_cell) {
568  number_of_cells_ += CHILDREN_NUMBER;
569  number_of_leaves_ += CHILDREN_NUMBER - 1;
570 
571  return p_cell->SubdivideCell();
572  }
573 
574 
575  int SubvidiveUntilSizeNormalized(double* coord, const double desired_size){
576  key_type x_key = CalcKeyNormalized(coord[0]);
577  key_type y_key = CalcKeyNormalized(coord[1]);
578  key_type z_key = CalcKeyNormalized(coord[2]);
579 
580  cell_type* cell = root_;
581 
582 
583  // I'm assuming that the desired size is also normalized to the [0,1] span
584  std::size_t scaled_size = std::size_t(desired_size * (1 << ROOT_LEVEL));
585 
586  if(scaled_size < (1 << MIN_LEVEL))
587  scaled_size = (1 << MIN_LEVEL);
588 
589  for (std::size_t i = ROOT_LEVEL; (std::size_t(1) << i) > scaled_size; i--) {
590  if (cell->IsLeaf()) {
591  SubdivideCell(cell);
592  }
593  cell = cell->pGetChild(x_key, y_key, z_key);
594  }
595 
596  return 0;
597  }
598 
599  int RefineWithUniformSizeNormalized(const double uniform_size){
600  const double min_size = double(1 << MIN_LEVEL) / double(1 << ROOT_LEVEL);
601  double cell_size = uniform_size;
602  if(cell_size < min_size)
603  cell_size = min_size;
604 
605  std::vector<cell_type*> cells_stack;
606  cells_stack.push_back(root_);
607 
608  while (!cells_stack.empty()) {
609  cell_type* cell = cells_stack.back();
610  cells_stack.pop_back();
611  if(CalcSizeNormalized(cell) > cell_size){
612  if (cell->IsLeaf()) {
613  SubdivideCell(cell);
614  }
615  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++)
616  cells_stack.push_back(cell->pGetChild(i));
617  }
618  }
619 
620 
621  return 0;
622  }
623 
624  void InsertNormalized(typename cell_type::pointer_type object){
625 
626  const double tolerance = 0.001 * double(1 << MIN_LEVEL) / double(1 << ROOT_LEVEL) ; // 0.1% of the min size
627 
628  double min_coord[3]={0.00, 0.00, 0.00};
629  double max_coord[3]={0.00, 0.00, 0.00};
630 
631 
632 
633  //
634  // to be added to configure
635 
636  configuration_type::GetBoundingBox(object, min_coord, max_coord);
637  //KRATOS_THROW_ERROR(std::logic_error,"To be added to configure", "")
638 
639  key_type min_x_key = CalcKeyNormalized(min_coord[0]);
640  key_type min_y_key = CalcKeyNormalized(min_coord[1]);
641  key_type min_z_key = CalcKeyNormalized(min_coord[2]);
642 
643  key_type max_x_key = CalcKeyNormalized(max_coord[0]);
644  key_type max_y_key = CalcKeyNormalized(max_coord[1]);
645  key_type max_z_key = CalcKeyNormalized(max_coord[2]);
646 
647  key_type delta_x = min_x_key^max_x_key;
648  key_type delta_y = min_y_key^max_y_key;
649  key_type delta_z = min_z_key^max_z_key;
650 
651  // finding the level of the cell containing the entire region
652  std::size_t min_level_1 = ROOT_LEVEL;
653  std::size_t min_level_2 = ROOT_LEVEL;
654  std::size_t min_level = ROOT_LEVEL;
655 
656  const std::size_t one = 1;
657  while (!(delta_x & (one << min_level_1)) && (min_level_1 > MIN_LEVEL)) min_level_1--;
658  while (!(delta_y & (one << min_level_2)) && (min_level_2 > min_level_1)) min_level_2--;
659  while (!(delta_z & (one << min_level)) && (min_level > min_level_2)) min_level--;
660  min_level++;
661 
662  cell_type* range_cell = root_;
663 
664  for (std::size_t i = ROOT_LEVEL; i > min_level ; i--) {
665  if (range_cell->IsLeaf()) {
666  //SubdivideCell(range_cell);
667  break;
668  }
669  range_cell = range_cell->pGetChild(min_x_key, min_y_key, min_z_key);
670  }
671 
672  // Now we have the cell (or leaf) containing the entire range and from now on we have to intersect the object with all childs
673  std::vector<cell_type*> cells_stack;
674  cells_stack.push_back(range_cell);
675  while (!cells_stack.empty()) {
676  cell_type* cell = cells_stack.back();
677  cells_stack.pop_back();
678  if (cell->HasChildren()) {
679  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++){
680  //abel. to be optimized
681  cell_type* child=cell->pGetChild(i);
682  double low[3];
683  double high[3];
684  child->GetMinPointNormalized(low);
685  child->GetMaxPointNormalized(high);
686  if (Collides(min_coord, max_coord, low, high))
687  cells_stack.push_back(child);
688  }
689  } else{
690  // we are in a leaf and we can check if it intersects with the object
691  double cell_min_point[3];
692  double cell_max_point[3];
693 
694  cell->GetMinPointNormalized(cell_min_point);
695  cell->GetMaxPointNormalized(cell_max_point);
696 
697  // I have to put this in no normailzed part. Pooyan.
698 // ScaleBackToOriginalCoordinate(cell_min_point);
699 // ScaleBackToOriginalCoordinate(cell_max_point);
700 
701  const int is_intersected = /*configuration_type::*/IsIntersected(object,tolerance, cell_min_point, cell_max_point);
702  if(is_intersected)
703  cell->Insert(object);
704 
705  }
706  }
707  }
708 
709  void Insert(typename cell_type::pointer_type object){
710 
711  const double tolerance = 0.001 * double(1 << MIN_LEVEL) / double(1 << ROOT_LEVEL) ; // 0.1% of the min size
712 
713  double min_coord[3]={0.00, 0.00, 0.00};
714  double max_coord[3]={0.00, 0.00, 0.00};
715 
716  //
717  // to be added to configure
718 
719  configuration_type::GetBoundingBox(object, min_coord, max_coord);
720  //KRATOS_THROW_ERROR(std::logic_error,"To be added to configure", "")
721  NormalizeCoordinates(min_coord);
722  NormalizeCoordinates(max_coord);
723 
724  key_type min_x_key = CalcKeyNormalized(min_coord[0]);
725  key_type min_y_key = CalcKeyNormalized(min_coord[1]);
726  key_type min_z_key = CalcKeyNormalized(min_coord[2]);
727 
728  key_type max_x_key = CalcKeyNormalized(max_coord[0]);
729  key_type max_y_key = CalcKeyNormalized(max_coord[1]);
730  key_type max_z_key = CalcKeyNormalized(max_coord[2]);
731 
732  key_type delta_x = min_x_key^max_x_key;
733  key_type delta_y = min_y_key^max_y_key;
734  key_type delta_z = min_z_key^max_z_key;
735 
736  // finding the level of the cell containing the entire region
737  std::size_t min_level_1 = ROOT_LEVEL;
738  std::size_t min_level_2 = ROOT_LEVEL;
739  std::size_t min_level = ROOT_LEVEL;
740 
741  const std::size_t one = 1;
742  while (!(delta_x & (one << min_level_1)) && (min_level_1 > MIN_LEVEL)) min_level_1--;
743  while (!(delta_y & (one << min_level_2)) && (min_level_2 > min_level_1)) min_level_2--;
744  while (!(delta_z & (one << min_level)) && (min_level > min_level_2)) min_level--;
745  min_level++;
746 
747  cell_type* range_cell = root_;
748 
749  for (std::size_t i = ROOT_LEVEL; i > min_level ; i--) {
750  if (range_cell->IsLeaf()) {
751  //SubdivideCell(range_cell);
752  break;
753  }
754  range_cell = range_cell->pGetChild(min_x_key, min_y_key, min_z_key);
755 
756  }
757 
758  // Now we have the cell (or leaf) containing the entire range and from now on we have to intersect the object with all childs
759  std::vector<cell_type*> cells_stack;
760  cells_stack.push_back(range_cell);
761  while (!cells_stack.empty()) {
762  cell_type* cell = cells_stack.back();
763  cells_stack.pop_back();
764  if (cell->HasChildren()) {
765  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++){
766  //abel. to be optimized
767  cell_type* child=cell->pGetChild(i);
768  double low[3];
769  double high[3];
770  child->GetMinPointNormalized(low);
771  child->GetMaxPointNormalized(high);
772  if (Collides(min_coord, max_coord, low, high))
773  cells_stack.push_back(child);
774  }
775  } else{
776  // we are in a leaf and we can check if it intersects with the object
777  double cell_min_point[3];
778  double cell_max_point[3];
779 
780  cell->GetMinPointNormalized(cell_min_point);
781  cell->GetMaxPointNormalized(cell_max_point);
782 
783  // I have to put this in no normailzed part. Pooyan.
784  ScaleBackToOriginalCoordinate(cell_min_point);
785  ScaleBackToOriginalCoordinate(cell_max_point);
786 
787  const int is_intersected = /*configuration_type::*/IsIntersected(object,tolerance, cell_min_point, cell_max_point);
788  if(is_intersected)
789  cell->Insert(object);
790 
791  }
792  }
793 
794 
795 // std::cout << "min_coord : [" << min_coord[0] << "," << min_coord[1] << "," << min_coord[2] << std::endl;
796 // std::cout << "max_coord : [" << max_coord[0] << "," << max_coord[1] << "," << max_coord[2] << std::endl;
797 
798 
799 
800  }
801 
809  typename cell_type::pointer_type pObject,
810  std::vector<cell_type*>& rLeaves,
811  const double ToleranceCoefficient = 0.001 // 0.1% of the min size
812  )
813  {
814  const double tolerance = ToleranceCoefficient * double(1 << MIN_LEVEL) / double(1 << ROOT_LEVEL);
815 
816  double min_coord[3]={0.00, 0.00, 0.00};
817  double max_coord[3]={0.00, 0.00, 0.00};
818 
819  // TODO: To be added to configure
820 
821  configuration_type::GetBoundingBox(pObject, min_coord, max_coord);
822  NormalizeCoordinates(min_coord);
823  NormalizeCoordinates(max_coord);
824 
825  key_type min_x_key = CalcKeyNormalized(min_coord[0]);
826  key_type min_y_key = CalcKeyNormalized(min_coord[1]);
827  key_type min_z_key = CalcKeyNormalized(min_coord[2]);
828 
829  key_type max_x_key = CalcKeyNormalized(max_coord[0]);
830  key_type max_y_key = CalcKeyNormalized(max_coord[1]);
831  key_type max_z_key = CalcKeyNormalized(max_coord[2]);
832 
833  key_type delta_x = min_x_key^max_x_key;
834  key_type delta_y = min_y_key^max_y_key;
835  key_type delta_z = min_z_key^max_z_key;
836 
837  // Finding the level of the cell containing the entire region
838  std::size_t min_level_1 = ROOT_LEVEL;
839  std::size_t min_level_2 = ROOT_LEVEL;
840  std::size_t min_level = ROOT_LEVEL;
841 
842  const std::size_t one = 1;
843  while (!(delta_x & (one << min_level_1)) && (min_level_1 > MIN_LEVEL)) min_level_1--;
844  while (!(delta_y & (one << min_level_2)) && (min_level_2 > min_level_1)) min_level_2--;
845  while (!(delta_z & (one << min_level)) && (min_level > min_level_2)) min_level--;
846  min_level++;
847 
848  cell_type* range_cell = root_;
849 
850  for (std::size_t i = ROOT_LEVEL; i > min_level ; i--) {
851  if (range_cell->IsLeaf()) {
852  //SubdivideCell(range_cell);
853  break;
854  }
855  range_cell = range_cell->pGetChild(min_x_key, min_y_key, min_z_key);
856  }
857 
858  // Now we have the cell (or leaf) containing the entire range and from now on we have to intersect the pObject with all childs
859  std::vector<cell_type*> cells_stack;
860  cells_stack.push_back(range_cell);
861  while (!cells_stack.empty()) {
862  cell_type* cell = cells_stack.back();
863  cells_stack.pop_back();
864  if (cell->HasChildren()) {
865  for (std::size_t i = 0; i < CHILDREN_NUMBER; i++) {
866  // TODO: Abel. to be optimized
867  cell_type* child=cell->pGetChild(i);
868  double low[3];
869  double high[3];
870  child->GetMinPointNormalized(low);
871  child->GetMaxPointNormalized(high);
872  if (Collides(min_coord, max_coord, low, high)) {
873  cells_stack.push_back(child);
874  }
875  }
876  } else {
877  // we are in a leaf and we can check if it intersects with the pObject
878  double cell_min_point[3];
879  double cell_max_point[3];
880 
881  cell->GetMinPointNormalized(cell_min_point);
882  cell->GetMaxPointNormalized(cell_max_point);
883 
884  // I have to put this in no normailzed part. Pooyan.
885  ScaleBackToOriginalCoordinate(cell_min_point);
886  ScaleBackToOriginalCoordinate(cell_max_point);
887 
888  const bool is_intersected = IsIntersected(pObject,tolerance, cell_min_point, cell_max_point);
889 
890  if(is_intersected) {
891  rLeaves.push_back(cell);
892  }
893  }
894  }
895  }
896 
897 
898  inline bool IsIntersected(typename cell_type::pointer_type rObject, double Tolerance, const double* rLowPoint, const double* rHighPoint)
899  {
900  Point low_point(rLowPoint[0] - Tolerance, rLowPoint[1] - Tolerance, rLowPoint[2] - Tolerance);
901  Point high_point(rHighPoint[0] + Tolerance, rHighPoint[1] + Tolerance, rHighPoint[2] + Tolerance);
902 
903 
904  return HasIntersection(rObject->GetGeometry(), low_point, high_point);
905  }
906 
910  virtual bool HasIntersection(
911  GeometryType& rGeometry,
912  const Point& rLowPoint,
913  const Point& rHighPoint
914  )
915  {
916  return rGeometry.HasIntersection(rLowPoint, rHighPoint);
917  }
918 
919  cell_type* pGetCellContainRegion(key_type min_x_key, key_type min_y_key, key_type min_z_key,
920  key_type max_x_key, key_type max_y_key, key_type max_z_key)
921  {
922  cell_type* cell = root_;
923 
924  }
925 
926 
930 
932  return root_;
933  }
934 
935 
939 
940 
944 
945  void PrintGiDMesh(std::ostream & rOStream) const {
946  std::vector<cell_type*> leaves;
947 
948  GetAllLeavesVector(leaves);
949 
950  std::cout << "writing " << leaves.size() << " leaves" << std::endl;
951  rOStream << "MESH \"leaves\" dimension 3 ElemType Hexahedra Nnode 8" << std::endl;
952  rOStream << "# color 96 96 96" << std::endl;
953  rOStream << "Coordinates" << std::endl;
954  rOStream << "# node number coordinate_x coordinate_y coordinate_z " << std::endl;
955 
956  std::size_t node_index = 1;
957  for (std::size_t i = 0; i < leaves.size(); i++) {
958  cell_type* cell = leaves[i];
959  double min_point[3];
960  cell->GetMinPoint(min_point);
961 
962  double cell_size = cell->CalcSize();
963 
964  for (std::size_t j = 0; j < 2; j++)
965  for (std::size_t k = 0; k < 2; k++)
966  for (std::size_t h = 0; h < 2; h++) {
967  rOStream << node_index++ << " " << min_point[0] + j * cell_size << " " << min_point[1] + k * cell_size << " " << min_point[2] + h * cell_size << std::endl;
968  }
969  }
970 
971  rOStream << "end coordinates" << std::endl;
972  rOStream << "Elements" << std::endl;
973  rOStream << "# element node_1 node_2 node_3 material_number" << std::endl;
974 
975  for (std::size_t i = 0; i < leaves.size(); i++) {
976  if ((leaves[i]->pGetData()))
977  rOStream << i + 1 << " " << 8 * i + 1 << " " << 8 * i + 2 << " " << 8 * i + 4 << " " << 8 * i + 3 << " " << 8 * i + 5 << " " << 8 * i + 6 << " " << 8 * i + 8 << " " << 8 * i + 7 << " " << leaves[i]->GetLevel() + 100 << std::endl;
978  else
979  rOStream << i + 1 << " " << 8 * i + 1 << " " << 8 * i + 2 << " " << 8 * i + 4 << " " << 8 * i + 3 << " " << 8 * i + 5 << " " << 8 * i + 6 << " " << 8 * i + 8 << " " << 8 * i + 7 << " " << int(leaves[i]->GetLevel()) << std::endl;
980 
981  }
982  rOStream << "end elements" << std::endl;
983 
984  }
985 
986  double GetCoordinateNormalized(key_type key) const {
987  const double scale = 1.00 / (1 << ROOT_LEVEL);
988 
989  return static_cast<double>(key * scale);
990  }
991 
992  void PrintGiDMeshNew(std::ostream & rOStream) const {
993  std::vector<cell_type*> leaves;
994 
995  GetAllLeavesVector(leaves);
996 
997  std::cout << "writing " << leaves.size() << " leaves" << std::endl;
998  rOStream << "MESH \"leaves\" dimension 3 ElemType Hexahedra Nnode 8" << std::endl;
999  rOStream << "# color 96 96 96" << std::endl;
1000  rOStream << "Coordinates" << std::endl;
1001  rOStream << "# node number coordinate_x coordinate_y coordinate_z " << std::endl;
1002  std::size_t node_number = 0;
1003  // std::size_t node_index = 1;
1004  for (std::size_t i = 0; i < leaves.size(); i++) {
1005  cell_type* leaf = leaves[i];
1006  for (std::size_t i_point = 0; i_point < 8; i_point++) {
1007  std::size_t node_id = (*(leaf->pGetData()))[i_point]->Id();
1008  if (node_id > node_number) {
1009  key_type point_key[3];
1010  leaf->GetKey(i_point, point_key);
1011  double point_coordinate[3];
1012 
1013  for (std::size_t j = 0; j < DIMENSION; j++) {
1014  point_coordinate[j] = leaf->GetCoordinate(point_key[j]);
1015  }
1016  rOStream << node_id << " " << point_coordinate[0] << " " << point_coordinate[1] << " " << point_coordinate[2] << std::endl;
1017  node_number++;
1018  }
1019  }
1020  }
1021 
1022  rOStream << "end coordinates" << std::endl;
1023  rOStream << "Elements" << std::endl;
1024  rOStream << "# element node_1 node_2 node_3 material_number" << std::endl;
1025 
1026  for (std::size_t i = 0; i < leaves.size(); i++) {
1027  cell_type* leaf = leaves[i];
1028  rOStream << i + 1 << " ";
1029  for (std::size_t i_point = 0; i_point < 8; i_point++)
1030  rOStream << (*(leaf->pGetData()))[i_point]->Id() << " ";
1031 
1032  rOStream << std::endl;
1033  }
1034  rOStream << "end elements" << std::endl;
1035 
1036  }
1037 
1039 
1040  virtual std::string Info() const {
1041  return "Octree";
1042  }
1043 
1045 
1046  virtual void PrintInfo(std::ostream & rOStream) const {
1047  rOStream << Info();
1048  }
1049 
1051 
1052  virtual void PrintData(std::ostream & rOStream) const {
1053  rOStream << "Number of cells : " << number_of_cells_ << std::endl;
1054  rOStream << "Number of leaves : " << number_of_leaves_ << std::endl;
1055  //rOStream << *root_;
1056  }
1057 
1058 
1062 
1063 
1065 
1066  private:
1069 
1070 
1074 
1075  cell_type* root_;
1076 
1077  std::size_t number_of_cells_;
1078  std::size_t number_of_leaves_;
1079  std::size_t levels_;
1080 
1081  coordinate_type mOffset[3];
1082  coordinate_type mScaleFactor[3];
1083 
1084 
1088 
1089 
1093 
1094 
1098 
1099 
1103 
1104 
1108 
1110 
1111  //OctreeBinary & operator=(OctreeBinary const& rOther) {
1112  // return *this;
1113  //}
1114 
1116 
1117  //OctreeBinary(OctreeBinary const& rOther) {
1118 
1119  //}
1120 
1121 
1123 
1124  }; // Class Octree
1125 
1127 
1130 
1131 
1135 
1136 
1138  // inline std::istream & operator >>(std::istream& rIStream,
1139  // Octree& rThis);
1140 
1142 
1143  template <class TCellType>
1144  inline std::ostream & operator <<(std::ostream& rOStream,
1145  const OctreeBinary<TCellType>& rThis) {
1146  rThis.PrintInfo(rOStream);
1147  rOStream << std::endl;
1148  rThis.PrintData(rOStream);
1149 
1150  return rOStream;
1151  }
1153 
1155 
1156 } // namespace Kratos.
1157 
1158 
Geometry base class.
Definition: geometry.h:71
virtual bool HasIntersection(const GeometryType &ThisGeometry) const
Definition: geometry.h:1453
This class defines the node.
Definition: node.h:65
Short class definition.
Definition: octree_binary.h:60
virtual void PrintInfo(std::ostream &rOStream) const
Print information about this object.
Definition: octree_binary.h:1046
OctreeBinary(const double *NewScaleFactor, const double *NewOffset)
Definition: octree_binary.h:100
cell_type * pGetRightCell(const cell_type *p_cell)
Definition: octree_binary.h:469
cell_type * pGetBottomCell(cell_type *p_cell, std::size_t level)
Definition: octree_binary.h:541
cell_type * pGetFrontCell(const cell_type *p_cell)
Definition: octree_binary.h:501
int SubdivideCell(cell_type *p_cell)
Definition: octree_binary.h:567
cell_type * pGetLeftCell(cell_type *p_cell, std::size_t level)
Definition: octree_binary.h:461
TCellType cell_type
Definition: octree_binary.h:68
void SetBoundingBox(const coordinate_type *Low, const coordinate_type *High)
Definition: octree_binary.h:122
cell_type * pGetBottomCell(const cell_type *p_cell)
Definition: octree_binary.h:533
cell_type::key_type key_type
Definition: octree_binary.h:70
void Constrain2To1()
Definition: octree_binary.h:243
int SubvidiveUntilSizeNormalized(double *coord, const double desired_size)
Definition: octree_binary.h:575
void GetLeavesInBoundingBoxNormalized(const double *coord1, const double *coord2, std::vector< cell_type * > &leaves) const
Definition: octree_binary.h:331
virtual bool HasIntersection(GeometryType &rGeometry, const Point &rLowPoint, const Point &rHighPoint)
Detect if triangle and box are intersected.
Definition: octree_binary.h:910
virtual std::string Info() const
Turn back information as a string.
Definition: octree_binary.h:1040
void ScaleBackToOriginalCoordinate(coordinate_type *ThisCoordinates) const
Definition: octree_binary.h:175
cell_type * pGetBackCell(const cell_type *p_cell)
Definition: octree_binary.h:485
void NormalizeCoordinates(coordinate_type *Coordinates) const
Definition: octree_binary.h:141
void NormalizeCoordinates(const coordinate_type *Coordinates, coordinate_type *NormalizedCoordinates) const
Definition: octree_binary.h:149
int GetAllLeavesVector(std::vector< cell_type * > &all_leaves) const
Definition: octree_binary.h:404
void CalculateCoordinatesNormalized(const key_type *keys, coordinate_type *NormalizedCoordinates) const
Definition: octree_binary.h:163
bool Collides(const double *Low1, const double *High1, const double *Low2, const double *High2)
Definition: octree_binary.h:393
virtual ~OctreeBinary()
Destructor.
Definition: octree_binary.h:109
void Constrain2To1New()
Definition: octree_binary.h:286
int RefineWithUniformSizeNormalized(const double uniform_size)
Definition: octree_binary.h:599
cell_type * pGetNeighbourCell(cell_type *p_cell, std::size_t position, std::size_t direction)
Definition: octree_binary.h:558
cell_type * pGetLeftCell(const cell_type *p_cell)
Definition: octree_binary.h:453
double coordinate_type
Definition: octree_binary.h:74
cell_type::configuration_type configuration_type
Definition: octree_binary.h:72
cell_type * pGetRightCell(cell_type *p_cell, std::size_t level)
Definition: octree_binary.h:477
static constexpr std::size_t CHILDREN_NUMBER
Definition: octree_binary.h:80
key_type CalcKeyNormalized(coordinate_type coordinate) const
Definition: octree_binary.h:199
static constexpr std::size_t MAX_LEVEL
Definition: octree_binary.h:82
void CalculateCoordinateNormalized(const key_type key, coordinate_type &NormalizedCoordinate) const
Definition: octree_binary.h:158
void Insert(typename cell_type::pointer_type object)
Definition: octree_binary.h:709
void CalculateCoordinates(key_type *keys, coordinate_type *ResultCoordinates) const
Definition: octree_binary.h:169
Node NodeType
Definition: octree_binary.h:76
KRATOS_CLASS_POINTER_DEFINITION(OctreeBinary)
Pointer definition of Octree.
Geometry< NodeType > GeometryType
Definition: octree_binary.h:78
void ScaleBackToOriginalCoordinate(const coordinate_type *ThisCoordinates, coordinate_type *ResultCoordinates) const
Definition: octree_binary.h:184
void GetIntersectedLeaves(typename cell_type::pointer_type pObject, std::vector< cell_type * > &rLeaves, const double ToleranceCoefficient=0.001)
This method fills the intersected leaves.
Definition: octree_binary.h:808
bool CheckConstrain2To1() const
Definition: octree_binary.h:238
OctreeBinary()
Default constructor.
Definition: octree_binary.h:92
void Insert(coordinate_type *point)
Definition: octree_binary.h:220
double CalcMinCellNormalizedSize() const
Definition: octree_binary.h:136
void InsertNormalized(typename cell_type::pointer_type object)
Definition: octree_binary.h:624
static constexpr std::size_t ROOT_LEVEL
Definition: octree_binary.h:83
cell_type * pGetFrontCell(cell_type *p_cell, std::size_t level)
Definition: octree_binary.h:509
bool IsIntersected(typename cell_type::pointer_type rObject, double Tolerance, const double *rLowPoint, const double *rHighPoint)
Definition: octree_binary.h:898
static constexpr std::size_t MIN_LEVEL
Definition: octree_binary.h:84
void PrintGiDMesh(std::ostream &rOStream) const
Definition: octree_binary.h:945
cell_type * pGetNeighbourCell(const cell_type *p_cell, std::size_t direction)
Definition: octree_binary.h:549
cell_type * pGetCellContainRegion(key_type min_x_key, key_type min_y_key, key_type min_z_key, key_type max_x_key, key_type max_y_key, key_type max_z_key)
Definition: octree_binary.h:919
static constexpr std::size_t DIMENSION
Definition: octree_binary.h:81
cell_type * pGetTopCell(const cell_type *p_cell)
Definition: octree_binary.h:517
double CalcSizeNormalized(const cell_type *cell) const
Definition: octree_binary.h:130
cell_type * pGetRoot()
Definition: octree_binary.h:931
cell_type * pGetBackCell(cell_type *p_cell, std::size_t level)
Definition: octree_binary.h:493
cell_type * pGetCell(key_type *keys, std::size_t level) const
Definition: octree_binary.h:441
virtual void PrintData(std::ostream &rOStream) const
Print object's data.
Definition: octree_binary.h:1052
cell_type * pGetCellNormalized(const coordinate_type *point) const
Definition: octree_binary.h:420
cell_type * pGetTopCell(cell_type *p_cell, std::size_t level)
Definition: octree_binary.h:525
void InsertNormalized(coordinate_type *point)
Definition: octree_binary.h:204
double GetCoordinateNormalized(key_type key) const
Definition: octree_binary.h:986
void PrintGiDMeshNew(std::ostream &rOStream) const
Definition: octree_binary.h:992
cell_type * pGetCell(key_type *keys) const
Definition: octree_binary.h:429
Point class.
Definition: point.h:59
#define KRATOS_WATCH(variable)
Definition: define.h:806
pybind11::list keys(Parameters const &self)
Definition: add_kratos_parameters_to_python.cpp:32
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
REACTION_CHECK_STIFFNESS_FACTOR int
Definition: contact_structural_mechanics_application_variables.h:75
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
std::ostream & operator<<(std::ostream &rOStream, const LinearMasterSlaveConstraint &rThis)
output stream function
Definition: linear_master_slave_constraint.h:432
h
Definition: generate_droplet_dynamics.py:91
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int node_id
Definition: read_stl.py:12
integer i
Definition: TensorModule.f:17