PABLO  0.1
PArallel Balanced Linear Octree
 All Classes Functions Variables Pages
Class_Local_Tree_2D.tpp
1 
27 // =================================================================================== //
28 // CLASS SPECIALIZATION //
29 // =================================================================================== //
30 
31 template<>
33  // ------------------------------------------------------------------------------- //
34  // FRIENDSHIPS ------------------------------------------------------------------- //
35  template<int dim> friend class Class_Para_Tree;
36 
37  // ------------------------------------------------------------------------------- //
38  // TYPEDEFS ----------------------------------------------------------------------- //
39 
40  typedef vector<Class_Octant<2> > OctantsType;
41  typedef vector<Class_Intersection<2> > IntersectionsType;
42  typedef vector<uint32_t> u32vector;
43  typedef vector<uint64_t> u64vector;
44  typedef vector<vector<uint32_t> > u32vector2D;
45  typedef vector<vector<uint64_t> > u64vector2D;
46 
47 
48  // ------------------------------------------------------------------------------- //
49  // MEMBERS ----------------------------------------------------------------------- //
50 
51 private:
52  OctantsType octants;
53  OctantsType ghosts;
54  IntersectionsType intersections;
55  u64vector globalidx_ghosts;
56  Class_Octant<2> first_desc;
57  Class_Octant<2> last_desc;
58  uint32_t size_ghosts;
59  uint8_t local_max_depth;
60  uint8_t balance_codim;
62  u32vector last_ghost_bros;
64  // connectivity
65  u32vector2D nodes;
66  u32vector2D connectivity;
68  u32vector2D ghostsnodes;
69  u32vector2D ghostsconnectivity;
72  // ------------------------------------------------------------------------------- //
73  // CONSTRUCTORS ------------------------------------------------------------------ //
74 
75 public:
77  Class_Octant<2> oct0;
78  Class_Octant<2> octf(MAX_LEVEL_2D,0,0);
79  Class_Octant<2> octl(MAX_LEVEL_2D,global2D.max_length-1,global2D.max_length-1);
80  octants.resize(1);
81  octants[0] = oct0;
82  first_desc = octf;
83  last_desc = octl;
84  size_ghosts = 0;
85  local_max_depth = 0;
86  balance_codim = 1;
87  };
88 
89  ~Class_Local_Tree(){};
90 
91  // ------------------------------------------------------------------------------- //
92  // METHODS ----------------------------------------------------------------------- //
93 
94  // Basic Get/Set methods --------------------------------------------------------- //
95 
96 private:
97  //public:
98  const Class_Octant<2> & getFirstDesc() const{
99  return first_desc;
100  };
101  const Class_Octant<2> & getLastDesc() const{
102  return last_desc;
103  };
104  uint32_t getSizeGhost() const{
105  return size_ghosts;
106  };
107  uint32_t getNumOctants() const{
108  return octants.size();
109  };
110  uint8_t getLocalMaxDepth() const{ // Get max depth reached in local tree
111  return local_max_depth;
112  };
113  int8_t getMarker(int32_t idx){ // Get refinement/coarsening marker for idx-th octant
114  return octants[idx].getMarker();
115  };
116  uint8_t getLevel(int32_t idx){ // Get refinement/coarsening marker for idx-th octant
117  return octants[idx].getLevel();
118  };
119  uint8_t getGhostLevel(int32_t idx){ // Get refinement/coarsening marker for idx-th ghost octant
120  return ghosts[idx].getLevel();
121  };
122  bool getBalance(int32_t idx){ // Get if balancing-blocked idx-th octant
123  return octants[idx].getNotBalance();
124  };
125 
129  uint8_t getBalanceCodim() const{
130  return balance_codim;
131  };
132 
133  void setMarker(int32_t idx, int8_t marker){ // Set refinement/coarsening marker for idx-th octant
134  octants[idx].setMarker(marker);
135  };
136  void setBalance(int32_t idx, bool balance){ // Set if balancing-blocked idx-th octant
137  octants[idx].setBalance(balance);
138  };
139 
143  void setBalanceCodim(uint8_t b21codim){
144  balance_codim = b21codim;
145  };
146 
147  void setFirstDesc(){
148  OctantsType::const_iterator firstOctant = octants.begin();
149  first_desc = Class_Octant<2>(MAX_LEVEL_2D,firstOctant->x,firstOctant->y);
150  };
151  void setLastDesc(){
152  OctantsType::const_iterator lastOctant = octants.end() - 1;
153  uint32_t x,y,delta;
154  delta = (uint32_t)pow(2.0,(double)((uint8_t)MAX_LEVEL_2D - lastOctant->level)) - 1;
155  x = lastOctant->x + delta;
156  y = lastOctant->y + delta;
157  last_desc = Class_Octant<2>(MAX_LEVEL_2D,x,y);
158 
159  };
160 
161  //-------------------------------------------------------------------------------- //
162  // Other methods ----------------------------------------------------------------- //
163 
164  Class_Octant<2>& extractOctant(uint32_t idx) {
165  return octants[idx];
166  };
167 
168  const Class_Octant<2>& extractOctant(uint32_t idx) const{
169  return octants[idx];
170  };
171 
172  Class_Octant<2>& extractGhostOctant(uint32_t idx) {
173  return ghosts[idx];
174  };
175 
176  const Class_Octant<2>& extractGhostOctant(uint32_t idx) const{
177  return ghosts[idx];
178  };
179 
180  // =================================================================================== //
181 
182  bool refine(){ // Refine local tree: refine one time octants with marker >0
183 
184  // Local variables
185  vector<uint32_t> last_child_index;
186  vector<Class_Octant<2> > children;
187  uint32_t idx, nocts, ilastch;
188  uint32_t offset = 0, blockidx;
189  uint8_t nchm1 = global2D.nchildren-1, ich;
190  bool dorefine = false;
191 
192  nocts = octants.size();
193  for (idx=0; idx<nocts; idx++){
194  if(octants[idx].getMarker() > 0 && octants[idx].getLevel() < MAX_LEVEL_2D){
195  last_child_index.push_back(idx+nchm1+offset);
196  offset += nchm1;
197  }
198  else{
199  // octants[idx].info[8] = false;
200  if (octants[idx].marker > 0){
201  octants[idx].marker = 0;
202  octants[idx].info[11] = true;
203  }
204  }
205  }
206  if (offset > 0){
207  octants.resize(octants.size()+offset);
208  blockidx = last_child_index[0]-nchm1;
209  idx = octants.size();
210  ilastch = last_child_index.size()-1;
211  while (idx>blockidx){
212  idx--;
213  if(idx == last_child_index[ilastch]){
214  children = octants[idx-offset].buildChildren();
215  for (ich=0; ich<global2D.nchildren; ich++){
216  octants[idx-ich] = (children[nchm1-ich]);
217  }
218  offset -= nchm1;
219  idx -= nchm1;
220  //Update local max depth
221  if (children[0].getLevel() > local_max_depth){
222  local_max_depth = children[0].getLevel();
223  }
224  if (children[0].getMarker() > 0){
225  //More Refinement to do
226  dorefine = true;
227  }
228  if (ilastch != 0){
229  ilastch--;
230  }
231  }
232  else {
233  octants[idx] = octants[idx-offset];
234  }
235  }
236  }
237 #if defined(__INTEL_COMPILER) || defined(__ICC)
238 #else
239  octants.shrink_to_fit();
240 #endif
241  nocts = octants.size();
242 
243  setFirstDesc();
244  setLastDesc();
245 
246  return dorefine;
247 
248  };
249 
250  // =================================================================================== //
251 
252  bool coarse(){ // Coarse local tree: coarse one time family of octants with marker <0
253  // Local variables // (if at least one octant of family has marker>=0 set marker=0 for the entire family)
254  vector<uint32_t> first_child_index;
255  Class_Octant<2> father;
256  uint32_t nocts;
257  uint32_t idx, idx2;
258  uint32_t offset;
259  uint32_t idx2_gh;
260  uint32_t nidx;
261  int8_t markerfather, marker;
262  uint8_t nbro, nstart, nend;
263  uint8_t nchm1 = global2D.nchildren-1;
264  bool docoarse = false;
265  bool wstop = false;
266 
267  //------------------------------------------ //
268  // Initialization
269 
270  nbro = nstart = nend = 0;
271  nidx = offset = 0;
272 
273  idx2_gh = 0;
274 
275  nocts = octants.size();
276  size_ghosts = ghosts.size();
277 
278  // Init first and last desc (even if already calculated)
279  setFirstDesc();
280  setLastDesc();
281 
282  //------------------------------------------ //
283 
284  // Set index for start and end check for ghosts
285  if (ghosts.size()){
286  while(idx2_gh < size_ghosts && ghosts[idx2_gh].computeMorton() <= last_desc.computeMorton()){
287  idx2_gh++;
288  }
289  idx2_gh = min((size_ghosts-1), idx2_gh);
290  }
291 
292  // Check and coarse internal octants
293  for (idx=0; idx<nocts; idx++){
294  if(octants[idx].getMarker() < 0 && octants[idx].getLevel() > 0){
295  nbro = 0;
296  father = octants[idx].buildFather();
297  // Check if family is to be coarsened
298  for (idx2=idx; idx2<idx+global2D.nchildren; idx2++){
299  if (idx2<nocts){
300  if(octants[idx2].getMarker() < 0 && octants[idx2].buildFather() == father){
301  nbro++;
302  }
303  }
304  }
305  if (nbro == global2D.nchildren){
306  nidx++;
307  first_child_index.push_back(idx);
308  idx = idx2-1;
309  }
310 // else{
311 // if (idx < (nocts>global2D.nchildren)*(nocts-global2D.nchildren)){
312 // octants[idx].setMarker(0);
313 // octants[idx].info[11] = true;
314 // }
315 // }
316  }
317  // else{
318  // // octants[idx].info[13] = false;
319  // }
320  }
321  uint32_t nblock = nocts;
322  uint32_t nfchild = first_child_index.size();
323  if (nidx!=0){
324  nblock = nocts - nidx*nchm1;
325  nidx = 0;
326  for (idx=0; idx<nblock; idx++){
327  if (nidx < nfchild){
328  if (idx+offset == first_child_index[nidx]){
329  markerfather = -MAX_LEVEL_2D;
330  father = octants[idx+offset].buildFather();
331  for (uint32_t iii=0; iii<12; iii++){
332  father.info[iii] = false;
333  }
334  for(idx2=0; idx2<global2D.nchildren; idx2++){
335  if (markerfather < octants[idx+offset+idx2].getMarker()+1){
336  markerfather = octants[idx+offset+idx2].getMarker()+1;
337  }
338  for (uint32_t iii=0; iii<12; iii++){
339  father.info[iii] = father.info[iii] || octants[idx+offset+idx2].info[iii];
340  }
341  }
342  father.info[9] = true;
343  father.info[11] = true;
344  if (markerfather < 0){
345  docoarse = true;
346  }
347  father.setMarker(markerfather);
348  octants[idx] = father;
349  offset += nchm1;
350  nidx++;
351  }
352  else{
353  octants[idx] = octants[idx+offset];
354  }
355  }
356  else{
357  octants[idx] = octants[idx+offset];
358  }
359  }
360  }
361  octants.resize(nblock);
362 #if defined(__INTEL_COMPILER) || defined(__ICC)
363 #else
364  octants.shrink_to_fit();
365 #endif
366  nocts = octants.size();
367 
368  // End on ghosts
369  if (ghosts.size() && nocts > 0){
370 // if ((ghosts[idx2_gh].getMarker() < 0) && (octants[nocts-1].getMarker() < 0)){
371  if (ghosts[idx2_gh].buildFather() == octants[nocts-1].buildFather()){
372  father = ghosts[idx2_gh].buildFather();
373  for (uint32_t iii=0; iii<12; iii++){
374  father.info[iii] = false;
375  }
376  markerfather = ghosts[idx2_gh].getMarker()+1;
377  nbro = 0;
378  idx = idx2_gh;
379  marker = ghosts[idx].getMarker();
380  while(marker < 0 && ghosts[idx].buildFather() == father){
381  nbro++;
382  if (markerfather < ghosts[idx].getMarker()+1){
383  markerfather = ghosts[idx].getMarker()+1;
384  }
385  for (uint32_t iii=0; iii<global2D.nfaces; iii++){
386  father.info[iii] = father.info[iii] || ghosts[idx].info[iii];
387  }
388  father.info[10] = father.info[10] || ghosts[idx].info[10];
389  idx++;
390  if(idx == size_ghosts){
391  break;
392  }
393  marker = ghosts[idx].getMarker();
394 // for (uint32_t iii=0; iii<12; iii++){
395 // father.info[iii] = father.info[iii] || ghosts[idx].info[iii];
396 // }
397  }
398  nend = 0;
399  idx = nocts-1;
400  marker = octants[idx].getMarker();
401  while(marker < 0 && octants[idx].buildFather() == father && idx >= 0){
402  nbro++;
403  nend++;
404  if (markerfather < octants[idx].getMarker()+1){
405  markerfather = octants[idx].getMarker()+1;
406  }
407  idx--;
408  marker = octants[idx].getMarker();
409  if (wstop){
410  break;
411  }
412  if (idx==0){
413  wstop = true;
414  }
415  }
416  if (nbro == global2D.nchildren){
417  offset = nend;
418  }
419  else{
420  nend = 0;
421 // for(uint32_t ii=nocts-global2D.nchildren; ii<nocts; ii++){
422 // octants[ii].setMarker(0);
423 // octants[ii].info[11] = true;
424 // }
425  }
426  }
427 
428  if (nend != 0){
429  for (idx=0; idx < nend; idx++){
430  for (uint32_t iii=0; iii<12; iii++){
431  father.info[iii] = father.info[iii] || octants[nocts-idx-1].info[iii];
432  }
433  }
434  father.info[9] = true;
435  father.info[11] = true;
436  if (markerfather < 0){
437  docoarse = true;
438  }
439  father.setMarker(markerfather);
440  octants.resize(nocts-offset);
441  octants.push_back(father);
442 #if defined(__INTEL_COMPILER) || defined(__ICC)
443 #else
444  octants.shrink_to_fit();
445 #endif
446  nocts = octants.size();
447  }
448  }
449 
450  // Set final first and last desc
451  if(nocts>0){
452  setFirstDesc();
453  setLastDesc();
454  }
455  return docoarse;
456 
457  };
458 
459  // =================================================================================== //
460 
461  bool refine(u32vector & mapidx){ // Refine local tree: refine one time octants with marker >0
462  // mapidx[i] = index in old octants vector of the i-th octant (index of father if octant is new after)
463  // Local variables
464  vector<uint32_t> last_child_index;
465  vector<Class_Octant<2> > children;
466  uint32_t idx, nocts, ilastch;
467  uint32_t offset = 0, blockidx;
468  uint8_t nchm1 = global2D.nchildren-1, ich;
469  bool dorefine = false;
470 
471  nocts = octants.size();
472  for (idx=0; idx<nocts; idx++){
473  if(octants[idx].getMarker() > 0 && octants[idx].getLevel() < MAX_LEVEL_2D){
474  last_child_index.push_back(idx+nchm1+offset);
475  offset += nchm1;
476  }
477  else{
478  // octants[idx].info[8] = false;
479  if (octants[idx].marker > 0){
480  octants[idx].marker = 0;
481  octants[idx].info[11] = true;
482  }
483  }
484  }
485  if (offset > 0){
486  mapidx.resize(octants.size()+offset);
487 #if defined(__INTEL_COMPILER) || defined(__ICC)
488 #else
489  mapidx.shrink_to_fit();
490 #endif
491  octants.resize(octants.size()+offset);
492  blockidx = last_child_index[0]-nchm1;
493  idx = octants.size();
494  ilastch = last_child_index.size()-1;
495  while (idx>blockidx){
496  // while (idx>0){
497  idx--;
498  if(idx == last_child_index[ilastch]){
499  children = octants[idx-offset].buildChildren();
500  for (ich=0; ich<global2D.nchildren; ich++){
501  octants[idx-ich] = (children[nchm1-ich]);
502  mapidx[idx-ich] = mapidx[idx-offset];
503  }
504  offset -= nchm1;
505  idx -= nchm1;
506  //Update local max depth
507  if (children[0].getLevel() > local_max_depth){
508  local_max_depth = children[0].getLevel();
509  }
510  if (children[0].getMarker() > 0){
511  //More Refinement to do
512  dorefine = true;
513  }
514  if (ilastch != 0){
515  ilastch--;
516  }
517  }
518  else {
519  octants[idx] = octants[idx-offset];
520  mapidx[idx] = mapidx[idx-offset];
521  }
522  }
523  }
524 #if defined(__INTEL_COMPILER) || defined(__ICC)
525 #else
526  octants.shrink_to_fit();
527 #endif
528  nocts = octants.size();
529 
530  setFirstDesc();
531  setLastDesc();
532 
533  return dorefine;
534 
535  };
536 
537  // =================================================================================== //
538 
539  bool coarse(u32vector & mapidx){ // Coarse local tree: coarse one time family of octants with marker <0
540  // (if at least one octant of family has marker>=0 set marker=0 for the entire family)
541  // mapidx[i] = index in old octants vector of the i-th octant (index of father if octant is new after)
542  // Local variables
543  vector<uint32_t> first_child_index;
544  Class_Octant<2> father;
545  uint32_t nocts, nocts0;
546  uint32_t idx, idx2;
547  uint32_t offset;
548  uint32_t idx2_gh;
549  uint32_t nidx;
550  int8_t markerfather, marker;
551  uint8_t nbro, nend;
552  uint8_t nchm1 = global2D.nchildren-1;
553  bool docoarse = false;
554  bool wstop = false;
555 
556  //------------------------------------------ //
557  // Initialization
558 
559  nbro = nend = 0;
560  nidx = offset = 0;
561 
562  idx2_gh = 0;
563 
564  nocts = nocts0 = octants.size();
565  size_ghosts = ghosts.size();
566 
567 
568  // Init first and last desc (even if already calculated)
569  setFirstDesc();
570  setLastDesc();
571 
572  //------------------------------------------ //
573 
574  // Set index for start and end check for ghosts
575  if (ghosts.size()){
576  while(idx2_gh < size_ghosts && ghosts[idx2_gh].computeMorton() < last_desc.computeMorton()){
577  idx2_gh++;
578  }
579  idx2_gh = min((size_ghosts-1), idx2_gh);
580  }
581 
582  // Check and coarse internal octants
583  for (idx=0; idx<nocts; idx++){
584  if(octants[idx].getMarker() < 0 && octants[idx].getLevel() > 0){
585  nbro = 0;
586  father = octants[idx].buildFather();
587  // Check if family is to be refined
588  for (idx2=idx; idx2<idx+global2D.nchildren; idx2++){
589  if (idx2<nocts){
590  if(octants[idx2].getMarker() < 0 && octants[idx2].buildFather() == father){
591  nbro++;
592  }
593  }
594  }
595  if (nbro == global2D.nchildren){
596  nidx++;
597  first_child_index.push_back(idx);
598  idx = idx2-1;
599  }
600 // else{
601 // if (idx < (nocts>global2D.nchildren)*(nocts-global2D.nchildren)){
602 // octants[idx].setMarker(0);
603 // octants[idx].info[11] = true;
604 // }
605 // }
606  }
607  // else{
608  // // octants[idx].info[13] = false;
609  // }
610  }
611  uint32_t nblock = nocts;
612  uint32_t nfchild = first_child_index.size();
613  if (nidx!=0){
614  nblock = nocts - nidx*nchm1;
615  nidx = 0;
616  for (idx=0; idx<nblock; idx++){
617  if (nidx < nfchild){
618  if (idx+offset == first_child_index[nidx]){
619  markerfather = -MAX_LEVEL_2D;
620  father = octants[idx+offset].buildFather();
621  for (uint32_t iii=0; iii<12; iii++){
622  father.info[iii] = false;
623  }
624  for(idx2=0; idx2<global2D.nchildren; idx2++){
625  if (markerfather < octants[idx+offset+idx2].getMarker()+1){
626  markerfather = octants[idx+offset+idx2].getMarker()+1;
627  }
628  for (uint32_t iii=0; iii<12; iii++){
629  father.info[iii] = father.info[iii] || octants[idx+offset+idx2].info[iii];
630  }
631  }
632  father.info[9] = true;
633  father.info[11] = true;
634  if (markerfather < 0){
635  docoarse = true;
636  }
637  father.setMarker(markerfather);
638  octants[idx] = father;
639  mapidx[idx] = mapidx[idx+offset];
640  offset += nchm1;
641  nidx++;
642  }
643  else{
644  octants[idx] = octants[idx+offset];
645  mapidx[idx] = mapidx[idx+offset];
646  }
647  }
648  else{
649  octants[idx] = octants[idx+offset];
650  mapidx[idx] = mapidx[idx+offset];
651  }
652  }
653  }
654  octants.resize(nblock);
655 #if defined(__INTEL_COMPILER) || defined(__ICC)
656 #else
657  octants.shrink_to_fit();
658 #endif
659  nocts = octants.size();
660  mapidx.resize(nblock);
661 #if defined(__INTEL_COMPILER) || defined(__ICC)
662 #else
663  mapidx.shrink_to_fit();
664 #endif
665 
666  // End on ghosts
667  if (ghosts.size() && nocts > 0){
668 // if ((ghosts[idx2_gh].getMarker() < 0) && (octants[nocts-1].getMarker() < 0)){
669  if (ghosts[idx2_gh].buildFather() == octants[nocts-1].buildFather()){
670  father = ghosts[idx2_gh].buildFather();
671  for (uint32_t iii=0; iii<12; iii++){
672  father.info[iii] = false;
673  }
674  markerfather = ghosts[idx2_gh].getMarker()+1;
675  nbro = 0;
676  idx = idx2_gh;
677  marker = ghosts[idx].getMarker();
678  while(marker < 0 && ghosts[idx].buildFather() == father){
679  nbro++;
680  if (markerfather < ghosts[idx].getMarker()+1){
681  markerfather = ghosts[idx].getMarker()+1;
682  }
683  for (uint32_t iii=0; iii<global2D.nfaces; iii++){
684  father.info[iii] = father.info[iii] || ghosts[idx].info[iii];
685  }
686  father.info[10] = father.info[10] || ghosts[idx].info[10];
687  idx++;
688  if(idx == size_ghosts){
689  break;
690  }
691  marker = ghosts[idx].getMarker();
692 // for (int iii=0; iii<12; iii++){
693 // father.info[iii] = father.info[iii] || ghosts[idx].info[iii];
694 // }
695  }
696  nend = 0;
697  idx = nocts-1;
698  marker = octants[idx].getMarker();
699  while(marker < 0 && octants[idx].buildFather() == father && idx >= 0){
700  nbro++;
701  nend++;
702  if (markerfather < octants[idx].getMarker()+1){
703  markerfather = octants[idx].getMarker()+1;
704  }
705  idx--;
706  marker = octants[idx].getMarker();
707  if (wstop){
708  break;
709  }
710  if (idx==0){
711  wstop = true;
712  }
713  }
714  if (nbro == global2D.nchildren){
715  offset = nend;
716  }
717  else{
718  nend = 0;
719 // for(uint32_t ii=nocts-global2D.nchildren; ii<nocts; ii++){
720 // octants[ii].setMarker(0);
721 // octants[ii].info[11] = true;
722 // }
723  }
724  }
725 
726  if (nend != 0){
727  for (idx=0; idx < nend; idx++){
728  for (uint32_t iii=0; iii<12; iii++){
729  father.info[iii] = father.info[iii] || octants[nocts-idx-1].info[iii];
730  }
731  }
732  father.info[9] = true;
733  father.info[11] = true;
734  if (markerfather < 0){
735  docoarse = true;
736  }
737  father.setMarker(markerfather);
738  octants.resize(nocts-offset);
739  octants.push_back(father);
740 #if defined(__INTEL_COMPILER) || defined(__ICC)
741 #else
742  octants.shrink_to_fit();
743 #endif
744  nocts = octants.size();
745 // TODO DO THIS CORRECTION IN OTHER COARSE METHODS !!!
746  mapidx.resize(nocts);
747 #if defined(__INTEL_COMPILER) || defined(__ICC)
748 #else
749  mapidx.shrink_to_fit();
750 #endif
751  }
752 
753  }
754 
755  // Set final first and last desc
756  if(nocts>0){
757  setFirstDesc();
758  setLastDesc();
759  }
760  return docoarse;
761 
762  };
763 
764  // =================================================================================== //
765 
766  // Global refine of octree (one level every element)
767  bool globalRefine(){
768 
769  // Local variables
770  vector<uint32_t> last_child_index;
771  vector<Class_Octant<2> > children;
772  uint32_t idx, nocts, ilastch;
773  uint32_t offset = 0, blockidx;
774  uint8_t nchm1 = global2D.nchildren-1, ich;
775  bool dorefine = false;
776 
777  nocts = octants.size();
778  for (idx=0; idx<nocts; idx++){
779  octants[idx].setMarker(1);
780  if(octants[idx].getMarker() > 0 && octants[idx].getLevel() < MAX_LEVEL_2D){
781  last_child_index.push_back(idx+nchm1+offset);
782  offset += nchm1;
783  }
784  else{
785  // octants[idx].info[8] = false;
786  if (octants[idx].marker > 0){
787  octants[idx].marker = 0;
788  octants[idx].info[11] = true;
789  }
790  }
791  }
792  if (offset > 0){
793  octants.resize(octants.size()+offset);
794  blockidx = last_child_index[0]-nchm1;
795  idx = octants.size();
796  ilastch = last_child_index.size()-1;
797  while (idx>blockidx){
798  idx--;
799  if(idx == last_child_index[ilastch]){
800  children = octants[idx-offset].buildChildren();
801  for (ich=0; ich<global2D.nchildren; ich++){
802  octants[idx-ich] = (children[nchm1-ich]);
803  }
804  offset -= nchm1;
805  idx -= nchm1;
806  //Update local max depth
807  if (children[0].getLevel() > local_max_depth){
808  local_max_depth = children[0].getLevel();
809  }
810  if (children[0].getMarker() > 0){
811  //More Refinement to do
812  dorefine = true;
813  }
814  if (ilastch != 0){
815  ilastch--;
816  }
817  }
818  else {
819  octants[idx] = octants[idx-offset];
820  }
821  }
822  }
823 #if defined(__INTEL_COMPILER) || defined(__ICC)
824 #else
825  octants.shrink_to_fit();
826 #endif
827  nocts = octants.size();
828 
829  setFirstDesc();
830  setLastDesc();
831 
832  return dorefine;
833 
834  };
835 
836  // =================================================================================== //
837 
838  // Global coarse of octree (every marker set =-1)
839  bool globalCoarse(){
840  vector<uint32_t> first_child_index;
841  Class_Octant<2> father;
842  uint32_t nocts;
843  uint32_t idx, idx2;
844  uint32_t offset;
845  uint32_t idx2_gh;
846  uint32_t nidx;
847  int8_t markerfather, marker;
848  uint8_t nbro, nend;
849  uint8_t nchm1 = global2D.nchildren-1;
850  bool docoarse = false;
851  bool wstop = false;
852 
853  //------------------------------------------ //
854  // Initialization
855 
856  nbro = nend = 0;
857  nidx = offset = 0;
858 
859  idx2_gh = 0;
860 
861  nocts = octants.size();
862  size_ghosts = ghosts.size();
863 
864  // Init first and last desc (even if already calculated)
865  setFirstDesc();
866  setLastDesc();
867 
868  //------------------------------------------ //
869 
870  // Set index for start and end check for ghosts
871  if (ghosts.size()){
872  while(idx2_gh < size_ghosts && ghosts[idx2_gh].computeMorton() <= last_desc.computeMorton()){
873  idx2_gh++;
874  }
875  idx2_gh = min((size_ghosts-1), idx2_gh);
876  }
877 
878  // Check and coarse internal octants
879  for (idx=0; idx<nocts; idx++){
880  octants[idx].setMarker(-1);
881  if(octants[idx].getMarker() < 0 && octants[idx].getLevel() > 0){
882  nbro = 0;
883  father = octants[idx].buildFather();
884  // Check if family is to be coarsened
885  for (idx2=idx; idx2<idx+global2D.nchildren; idx2++){
886  if (idx2<nocts){
887  octants[idx2].setMarker(-1);
888  if(octants[idx2].getMarker() < 0 && octants[idx2].buildFather() == father){
889  nbro++;
890  }
891  }
892  }
893  if (nbro == global2D.nchildren){
894  nidx++;
895  first_child_index.push_back(idx);
896  idx = idx2-1;
897  }
898  else{
899  if (idx < (nocts>global2D.nchildren)*(nocts-global2D.nchildren)){
900  octants[idx].setMarker(0);
901  octants[idx].info[11] = true;
902  }
903  }
904  }
905  // else{
906  // // octants[idx].info[13] = false;
907  // }
908  }
909  uint32_t nblock = nocts;
910  if (nidx!=0){
911  nblock = nocts - nidx*nchm1;
912  nidx = 0;
913  uint32_t nfchild = first_child_index.size();
914  for (idx=0; idx<nblock; idx++){
915  if (nidx < nfchild){
916  if (idx+offset == first_child_index[nidx]){
917  markerfather = -MAX_LEVEL_2D;
918  father = octants[idx+offset].buildFather();
919  for (uint32_t iii=0; iii<12; iii++){
920  father.info[iii] = false;
921  }
922  for(idx2=0; idx2<global2D.nchildren; idx2++){
923  if (markerfather < octants[idx+offset+idx2].getMarker()+1){
924  markerfather = octants[idx+offset+idx2].getMarker()+1;
925  }
926  for (uint32_t iii=0; iii<12; iii++){
927  father.info[iii] = father.info[iii] || octants[idx+offset+idx2].info[iii];
928  }
929  }
930  father.info[9] = true;
931  if (markerfather < 0){
932  docoarse = true;
933  }
934  father.setMarker(markerfather);
935  octants[idx] = father;
936  offset += nchm1;
937  nidx++;
938  }
939  else{
940  octants[idx] = octants[idx+offset];
941  }
942  }
943  else{
944  octants[idx] = octants[idx+offset];
945  }
946  }
947  }
948  octants.resize(nblock);
949 #if defined(__INTEL_COMPILER) || defined(__ICC)
950 #else
951  octants.shrink_to_fit();
952 #endif
953  nocts = octants.size();
954 
955  // End on ghosts
956  if (ghosts.size() && nocts > 0){
957  ghosts[idx2_gh].setMarker(-1);
958  if ((ghosts[idx2_gh].getMarker() < 0) && (octants[nocts-1].getMarker() < 0)){
959  father = ghosts[idx2_gh].buildFather();
960  for (uint32_t iii=0; iii<12; iii++){
961  father.info[iii] = false;
962  }
963  markerfather = ghosts[idx2_gh].getMarker()+1;//-MAX_LEVEL_2D;
964  nbro = 0;
965  idx = idx2_gh;
966  ghosts[idx].setMarker(-1);
967  marker = ghosts[idx].getMarker();
968  while(marker < 0 && ghosts[idx].buildFather() == father){
969  nbro++;
970  if (markerfather < ghosts[idx].getMarker()+1){
971  markerfather = ghosts[idx].getMarker()+1;
972  }
973  idx++;
974  if(idx == size_ghosts){
975  break;
976  }
977  ghosts[idx].setMarker(-1);
978  marker = ghosts[idx].getMarker();
979  for (uint32_t iii=0; iii<12; iii++){
980  father.info[iii] = father.info[iii] || ghosts[idx].info[iii];
981  }
982  }
983  nend = 0;
984  idx = nocts-1;
985  octants[idx].setMarker(-1);
986  marker = octants[idx].getMarker();
987  while(marker < 0 && octants[idx].buildFather() == father && idx >= 0){
988  nbro++;
989  nend++;
990  if (markerfather < octants[idx].getMarker()+1){
991  markerfather = octants[idx].getMarker()+1;
992  }
993  idx--;
994  octants[idx].setMarker(-1);
995  marker = octants[idx].getMarker();
996  if (wstop){
997  break;
998  }
999  if (idx==0){
1000  wstop = true;
1001  }
1002  }
1003  if (nbro == global2D.nchildren){
1004  offset = nend;
1005  }
1006  else{
1007  nend = 0;
1008  for(uint32_t ii=nocts-global2D.nchildren; ii<nocts; ii++){
1009  octants[ii].setMarker(0);
1010  octants[ii].info[11] = true;
1011  }
1012  }
1013  }
1014 
1015  if (nend != 0){
1016  for (idx=0; idx < nend; idx++){
1017  for (uint32_t iii=0; iii<12; iii++){
1018  father.info[iii] = father.info[iii] || octants[nocts-idx-1].info[iii];
1019  }
1020  }
1021  father.info[9] = true;
1022  if (markerfather < 0){
1023  docoarse = true;
1024  }
1025  father.setMarker(markerfather);
1026  octants.resize(nocts-offset);
1027  octants.push_back(father);
1028 #if defined(__INTEL_COMPILER) || defined(__ICC)
1029 #else
1030  octants.shrink_to_fit();
1031 #endif
1032  nocts = octants.size();
1033  }
1034  }
1035 
1036  // Set final first and last desc
1037  if(nocts>0){
1038  setFirstDesc();
1039  setLastDesc();
1040  }
1041  return docoarse;
1042 
1043  };
1044 
1045  // =================================================================================== //
1046 
1047  // One level global refine with mapidx
1048  bool globalRefine(u32vector & mapidx){
1049 
1050  // Local variables
1051  vector<uint32_t> last_child_index;
1052  vector<Class_Octant<2> > children;
1053  uint32_t idx, nocts, ilastch;
1054  uint32_t offset = 0, blockidx;
1055  uint8_t nchm1 = global2D.nchildren-1, ich;
1056  bool dorefine = false;
1057 
1058  nocts = octants.size();
1059  for (idx=0; idx<nocts; idx++){
1060  octants[idx].setMarker(1);
1061  if(octants[idx].getMarker() > 0 && octants[idx].getLevel() < MAX_LEVEL_2D){
1062  last_child_index.push_back(idx+nchm1+offset);
1063  offset += nchm1;
1064  }
1065  else{
1066  // octants[idx].info[8] = false;
1067  if (octants[idx].marker > 0){
1068  octants[idx].marker = 0;
1069  octants[idx].info[11] = true;
1070  }
1071  }
1072  }
1073  if (offset > 0){
1074  mapidx.resize(octants.size()+offset);
1075 #if defined(__INTEL_COMPILER) || defined(__ICC)
1076 #else
1077  mapidx.shrink_to_fit();
1078 #endif
1079  octants.resize(octants.size()+offset);
1080  blockidx = last_child_index[0]-nchm1;
1081  idx = octants.size();
1082  ilastch = last_child_index.size()-1;
1083  while (idx>blockidx){
1084  // while (idx>0){
1085  idx--;
1086  if(idx == last_child_index[ilastch]){
1087  children = octants[idx-offset].buildChildren();
1088  for (ich=0; ich<global2D.nchildren; ich++){
1089  octants[idx-ich] = (children[nchm1-ich]);
1090  mapidx[idx-ich] = mapidx[idx-offset];
1091  }
1092  offset -= nchm1;
1093  idx -= nchm1;
1094  //Update local max depth
1095  if (children[0].getLevel() > local_max_depth){
1096  local_max_depth = children[0].getLevel();
1097  }
1098  if (children[0].getMarker() > 0){
1099  //More Refinement to do
1100  dorefine = true;
1101  }
1102  if (ilastch != 0){
1103  ilastch--;
1104  }
1105  }
1106  else {
1107  octants[idx] = octants[idx-offset];
1108  mapidx[idx] = mapidx[idx-offset];
1109  }
1110  }
1111  }
1112 #if defined(__INTEL_COMPILER) || defined(__ICC)
1113 #else
1114  octants.shrink_to_fit();
1115 #endif
1116  nocts = octants.size();
1117 
1118  setFirstDesc();
1119  setLastDesc();
1120 
1121  return dorefine;
1122 
1123  };
1124 
1125  // =================================================================================== //
1126 
1127  // One level global coarse with mapidx
1128  bool globalCoarse(u32vector & mapidx){
1129 
1130  // Local variables
1131  vector<uint32_t> first_child_index;
1132  Class_Octant<2> father;
1133  uint32_t nocts, nocts0;
1134  uint32_t idx, idx2;
1135  uint32_t offset;
1136  uint32_t idx2_gh;
1137  uint32_t nidx;
1138  int8_t markerfather, marker;
1139  uint8_t nbro, nstart, nend;
1140  uint8_t nchm1 = global2D.nchildren-1;
1141  bool docoarse = false;
1142  bool wstop = false;
1143 
1144  //------------------------------------------ //
1145  // Initialization
1146 
1147  nbro = nstart = nend = 0;
1148  nidx = offset = 0;
1149 
1150  idx2_gh = 0;
1151 
1152  nocts = nocts0 = octants.size();
1153  size_ghosts = ghosts.size();
1154 
1155 
1156  // Init first and last desc (even if already calculated)
1157  setFirstDesc();
1158  setLastDesc();
1159 
1160  //------------------------------------------ //
1161 
1162  // Set index for start and end check for ghosts
1163  if (ghosts.size()){
1164  while(idx2_gh < size_ghosts && ghosts[idx2_gh].computeMorton() < last_desc.computeMorton()){
1165  idx2_gh++;
1166  }
1167  idx2_gh = min((size_ghosts-1), idx2_gh);
1168  }
1169 
1170  // Check and coarse internal octants
1171  for (idx=0; idx<nocts; idx++){
1172  octants[idx].setMarker(-1);
1173  if(octants[idx].getMarker() < 0 && octants[idx].getLevel() > 0){
1174  nbro = 0;
1175  father = octants[idx].buildFather();
1176  // Check if family is to be refined
1177  for (idx2=idx; idx2<idx+global2D.nchildren; idx2++){
1178  if (idx2<nocts){
1179  octants[idx2].setMarker(-1);
1180  if(octants[idx2].getMarker() < 0 && octants[idx2].buildFather() == father){
1181  nbro++;
1182  }
1183  }
1184  }
1185  if (nbro == global2D.nchildren){
1186  nidx++;
1187  first_child_index.push_back(idx);
1188  idx = idx2-1;
1189  }
1190  else{
1191  if (idx < (nocts>global2D.nchildren)*(nocts-global2D.nchildren)){
1192  octants[idx].setMarker(0);
1193  octants[idx].info[11] = true;
1194  }
1195  }
1196  }
1197  // else{
1198  // // octants[idx].info[13] = false;
1199  // }
1200  }
1201  if (nidx!=0){
1202  uint32_t nblock = nocts - nidx*nchm1 - nstart;
1203  nidx = 0;
1204  uint32_t nfchild = first_child_index.size();
1205  //for (idx=0; idx<nblock; idx++){
1206  for (idx=0; idx<nocts-offset; idx++){
1207  if (nidx < nfchild){
1208  if (idx+offset == first_child_index[nidx]){
1209  markerfather = -MAX_LEVEL_2D;
1210  father = octants[idx+offset].buildFather();
1211  for (uint32_t iii=0; iii<12; iii++){
1212  father.info[iii] = false;
1213  }
1214  for(idx2=0; idx2<global2D.nchildren; idx2++){
1215  if (markerfather < octants[idx+offset+idx2].getMarker()+1){
1216  markerfather = octants[idx+offset+idx2].getMarker()+1;
1217  }
1218  for (uint32_t iii=0; iii<12; iii++){
1219  father.info[iii] = father.info[iii] || octants[idx+offset+idx2].info[iii];
1220  }
1221  }
1222  father.info[9] = true;
1223  if (markerfather < 0){
1224  docoarse = true;
1225  }
1226  father.setMarker(markerfather);
1227  octants[idx] = father;
1228  mapidx[idx] = mapidx[idx+offset];
1229  offset += nchm1;
1230  nidx++;
1231  }
1232  else{
1233  octants[idx] = octants[idx+offset];
1234  mapidx[idx] = mapidx[idx+offset];
1235  }
1236  }
1237  else{
1238  octants[idx] = octants[idx+offset];
1239  mapidx[idx] = mapidx[idx+offset];
1240  }
1241  }
1242  }
1243  octants.resize(nocts-offset);
1244 #if defined(__INTEL_COMPILER) || defined(__ICC)
1245 #else
1246  octants.shrink_to_fit();
1247 #endif
1248  nocts = octants.size();
1249  mapidx.resize(nocts);
1250 #if defined(__INTEL_COMPILER) || defined(__ICC)
1251 #else
1252  mapidx.shrink_to_fit();
1253 #endif
1254 
1255  // End on ghosts
1256  if (ghosts.size() && nocts > 0){
1257  ghosts[idx2_gh].setMarker(-1);
1258  if ((ghosts[idx2_gh].getMarker() < 0) && (octants[nocts-1].getMarker() < 0)){
1259  father = ghosts[idx2_gh].buildFather();
1260  markerfather = ghosts[idx2_gh].getMarker()+1;
1261  nbro = 0;
1262  idx = idx2_gh;
1263  ghosts[idx].setMarker(-1);
1264  marker = ghosts[idx].getMarker();
1265  while(marker < 0 && ghosts[idx].buildFather() == father){
1266  nbro++;
1267  if (markerfather < ghosts[idx].getMarker()+1){
1268  markerfather = ghosts[idx].getMarker()+1;
1269  }
1270  idx++;
1271  if(idx == size_ghosts){
1272  break;
1273  }
1274  ghosts[idx].setMarker(-1);
1275  marker = ghosts[idx].getMarker();
1276  }
1277  nend = 0;
1278  idx = nocts-1;
1279  octants[idx].setMarker(-1);
1280  marker = octants[idx].getMarker();
1281  while(marker < 0 && octants[idx].buildFather() == father && idx >= 0){
1282  nbro++;
1283  nend++;
1284  if (markerfather < octants[idx].getMarker()+1){
1285  markerfather = octants[idx].getMarker()+1;
1286  }
1287  idx--;
1288  octants[idx].setMarker(-1);
1289  marker = octants[idx].getMarker();
1290  if (wstop){
1291  break;
1292  }
1293  if (idx==0){
1294  wstop = true;
1295  }
1296  }
1297  if (nbro == global2D.nchildren){
1298  offset = nend;
1299  }
1300  else{
1301  nend = 0;
1302  for(uint32_t ii=nocts-global2D.nchildren; ii<nocts; ii++){
1303  octants[ii].setMarker(0);
1304  octants[ii].info[11] = true;
1305  }
1306  }
1307  }
1308 
1309  if (nend != 0){
1310  for (uint32_t iii=0; iii<12; iii++){
1311  father.info[iii] = false;
1312  }
1313  for (idx=0; idx < nend; idx++){
1314  for (uint32_t iii=0; iii<12; iii++){
1315  father.info[iii] = father.info[iii] || octants[nocts-idx-1].info[iii];
1316  }
1317  }
1318  father.info[9] = true;
1319  if (markerfather < 0){
1320  docoarse = true;
1321  }
1322  father.setMarker(markerfather);
1323  octants.resize(nocts-offset);
1324  octants.push_back(father);
1325 #if defined(__INTEL_COMPILER) || defined(__ICC)
1326 #else
1327  octants.shrink_to_fit();
1328 #endif
1329  nocts = octants.size();
1330  mapidx.resize(nocts-offset);
1331  mapidx.push_back(nocts0-nend);
1332 #if defined(__INTEL_COMPILER) || defined(__ICC)
1333 #else
1334  mapidx.shrink_to_fit();
1335 #endif
1336  }
1337 
1338  }
1339 
1340  // Set final first and last desc
1341  if(nocts>0){
1342  setFirstDesc();
1343  setLastDesc();
1344  }
1345  return docoarse;
1346 
1347  };
1348 
1349  // =================================================================================== //
1350 
1351  void checkCoarse(uint64_t lastDescPre, // Delete overlapping octants after coarse local tree. Check first and last descendants
1352  uint64_t firstDescPost){ // of process before and after the local process
1353  uint32_t idx;
1354  uint32_t nocts;
1355  uint64_t Morton;
1356  uint8_t toDelete = 0;
1357 
1358  nocts = getNumOctants();
1359  idx = 0;
1360  Morton = octants[idx].computeMorton();
1361  while(Morton <= lastDescPre && idx < nocts && Morton != 0){
1362  // To delete, the father is in proc before me
1363  toDelete++;
1364  idx++;
1365  Morton = octants[idx].computeMorton();
1366  }
1367  for(idx=0; idx<nocts-toDelete; idx++){
1368  octants[idx] = octants[idx+toDelete];
1369  }
1370  octants.resize(nocts-toDelete);
1371 #if defined(__INTEL_COMPILER) || defined(__ICC)
1372 #else
1373  octants.shrink_to_fit();
1374 #endif
1375  nocts = getNumOctants();
1376 
1377  setFirstDesc();
1378  setLastDesc();
1379 
1380  };
1381 
1382  // =================================================================================== //
1383 
1384  void checkCoarse(uint64_t lastDescPre, // Delete overlapping octants after coarse local tree. Check first and last descendants
1385  uint64_t firstDescPost, // of process before and after the local process
1386  u32vector & mapidx){
1387  uint32_t idx;
1388  uint32_t nocts;
1389  uint64_t Morton;
1390  uint8_t toDelete = 0;
1391 
1392  nocts = getNumOctants();
1393  idx = 0;
1394  Morton = octants[idx].computeMorton();
1395  while(Morton <= lastDescPre && idx < nocts && Morton != 0){
1396  // To delete, the father is in proc before me
1397  toDelete++;
1398  idx++;
1399  Morton = octants[idx].computeMorton();
1400  }
1401  for(idx=0; idx<nocts-toDelete; idx++){
1402  octants[idx] = octants[idx+toDelete];
1403  mapidx[idx] = mapidx[idx+toDelete];
1404  }
1405  octants.resize(nocts-toDelete);
1406 #if defined(__INTEL_COMPILER) || defined(__ICC)
1407 #else
1408  octants.shrink_to_fit();
1409 #endif
1410  mapidx.resize(nocts-toDelete);
1411 #if defined(__INTEL_COMPILER) || defined(__ICC)
1412 #else
1413  mapidx.shrink_to_fit();
1414 #endif
1415  nocts = getNumOctants();
1416 
1417  setFirstDesc();
1418  setLastDesc();
1419 
1420  };
1421 
1422  // =================================================================================== //
1423 
1424  void updateLocalMaxDepth(){ // Update max depth reached in local tree
1425  uint32_t noctants = getNumOctants();
1426  uint32_t i;
1427 
1428  local_max_depth = 0;
1429  for(i = 0; i < noctants; i++){
1430  if(octants[i].getLevel() > local_max_depth){
1431  local_max_depth = octants[i].getLevel();
1432  }
1433  }
1434 
1435  };
1436 
1437  // =================================================================================== //
1438 
1439  void findNeighbours(uint32_t idx, // Finds neighbours of idx-th octant through iface in vector octants.
1440  uint8_t iface, // Returns a vector (empty if iface is a bound face) with the index of neighbours
1441  u32vector & neighbours, // in their structure (octants or ghosts) and sets isghost[i] = true if the
1442  vector<bool> & isghost){ // i-th neighbour is ghost in the local tree
1443 
1444  uint64_t Morton, Mortontry;
1445  uint32_t noctants = getNumOctants();
1446  uint32_t idxtry;
1447  Class_Octant<2>* oct = &octants[idx];
1448  uint32_t size = oct->getSize();
1449 
1450 
1451  // TODO Create a global matrix
1452  //Alternative to switch case
1453  int8_t cx = int8_t((iface<2)*(int8_t(2*iface-1)));
1454  int8_t cy = int8_t((int8_t(iface/2))*(int8_t(2*iface-5)));
1455 
1456  isghost.clear();
1457  neighbours.clear();
1458 
1459  // Default if iface is nface<iface<0
1460  if (iface < 0 || iface > global2D.nfaces){
1461  return;
1462  }
1463 
1464  // Check if octants face is a process boundary
1465  if (oct->info[global2D.nfaces+iface] == false){
1466 
1467  // Check if octants face is a boundary
1468  if (oct->info[iface] == false){
1469 
1470  //Build Morton number of virtual neigh of same size
1471  Class_Octant<2> samesizeoct(oct->level, int32_t(oct->x)+int32_t(cx*size), int32_t(oct->y)+int32_t(cy*size));
1472  Morton = samesizeoct.computeMorton();
1473  // Search morton in octants
1474  // If a even face morton is lower than morton of oct, if odd higher
1475  // ---> can i search only before or after idx in octants
1476  int32_t jump = (oct->computeMorton() > Morton) ? int32_t(idx/2+1) : int32_t((noctants -idx)/2+1);
1477  idxtry = uint32_t(idx +((oct->computeMorton()<Morton)-(oct->computeMorton()>Morton))*jump);
1478  if (idxtry > noctants-1) idxtry = noctants-1;
1479  Mortontry = oct->computeMorton();
1480  while(abs(jump) > 0){
1481  Mortontry = octants[idxtry].computeMorton();
1482  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
1483  idxtry += jump;
1484  if (idxtry > noctants-1){
1485  if (jump > 0){
1486  idxtry = noctants - 1;
1487  jump = 0;
1488  }
1489  else if (jump < 0){
1490  idxtry = 0;
1491  jump = 0;
1492  }
1493  }
1494  }
1495  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
1496  //Found neighbour of same size
1497  isghost.push_back(false);
1498  neighbours.push_back(idxtry);
1499  return;
1500  }
1501  else{
1502  // Step until the mortontry lower than morton (one idx of distance)
1503  {
1504  while(octants[idxtry].computeMorton() < Morton){
1505  idxtry++;
1506  if(idxtry > noctants-1){
1507  idxtry = noctants-1;
1508  break;
1509  }
1510  }
1511  while(octants[idxtry].computeMorton() > Morton){
1512  idxtry--;
1513  if(idxtry > noctants-1){
1514  idxtry = 0;
1515  break;
1516  }
1517  }
1518  }
1519  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
1520  //Found neighbour of same size
1521  isghost.push_back(false);
1522  neighbours.push_back(idxtry);
1523  return;
1524  }
1525  // Compute Last discendent of virtual octant of same size
1526  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
1527  uint64_t Mortonlast = last_desc.computeMorton();
1528  Mortontry = octants[idxtry].computeMorton();
1529  int32_t Dx, Dy;
1530  int32_t Dxstar, Dystar;
1531  while(Mortontry < Mortonlast && idxtry < noctants){
1532  Dx = int32_t(abs(cx))*(-int32_t(oct->x) + int32_t(octants[idxtry].x));
1533  Dy = int32_t(abs(cy))*(-int32_t(oct->y) + int32_t(octants[idxtry].y));
1534  Dxstar = int32_t((cx-1)/2)*(octants[idxtry].getSize()) + int32_t((cx+1)/2)*size;
1535  Dystar = int32_t((cy-1)/2)*(octants[idxtry].getSize()) + int32_t((cy+1)/2)*size;
1536 
1537  uint32_t x0 = oct->x;
1538  uint32_t x1 = x0 + size;
1539  uint32_t y0 = oct->y;
1540  uint32_t y1 = y0 + size;
1541  uint32_t x0try = octants[idxtry].x;
1542  uint32_t x1try = x0try + octants[idxtry].getSize();
1543  uint32_t y0try = octants[idxtry].y;
1544  uint32_t y1try = y0try + octants[idxtry].getSize();
1545  uint8_t level = oct->level;
1546  uint8_t leveltry = octants[idxtry].getLevel();
1547 
1548  if (Dx == Dxstar && Dy == Dystar){
1549  if (leveltry > level){
1550  if((abs(cx)*((y0try>=y0)*(y0try<y1))) + (abs(cy)*((x0try>=x0)*(x0try<x1)))){
1551  neighbours.push_back(idxtry);
1552  isghost.push_back(false);
1553  }
1554  }
1555  if (leveltry < level){
1556  if((abs(cx)*((y0>=y0try)*(y0<y1try))) + (abs(cy)*((x0>=x0try)*(x0<x1try)))){
1557  neighbours.push_back(idxtry);
1558  isghost.push_back(false);
1559  }
1560  }
1561  }
1562 
1563  idxtry++;
1564  if(idxtry>noctants-1){
1565  break;
1566  }
1567  Mortontry = octants[idxtry].computeMorton();
1568  }
1569  return;
1570  }
1571  }
1572  else{
1573  // Boundary Face
1574  return;
1575  }
1576  }
1577  //--------------------------------------------------------------- //
1578  //--------------------------------------------------------------- //
1579  else{
1580  // Check if octants face is a boundary
1581  if (oct->info[iface] == false){
1582  // IF OCTANT FACE IS A PROCESS BOUNDARY SEARCH ALSO IN GHOSTS
1583 
1584  if (ghosts.size()>0){
1585  // Search in ghosts
1586 
1587  uint32_t idxghost = uint32_t(size_ghosts/2);
1588  Class_Octant<2>* octghost = &ghosts[idxghost];
1589 
1590  //Build Morton number of virtual neigh of same size
1591  Class_Octant<2> samesizeoct(oct->level, oct->x+cx*size, oct->y+cy*size);
1592  Morton = samesizeoct.computeMorton(); //mortonEncode_magicbits(oct->x-size,oct->y,oct->z);
1593  // Search morton in octants
1594  // If a even face morton is lower than morton of oct, if odd higher
1595  // ---> can i search only before or after idx in octants
1596  int32_t jump = (octghost->computeMorton() > Morton) ? int32_t(idxghost/2+1) : int32_t((size_ghosts -idxghost)/2+1);
1597  idxtry = uint32_t(idxghost +((octghost->computeMorton()<Morton)-(octghost->computeMorton()>Morton))*jump);
1598  if (idxtry > ghosts.size()-1) idxtry = ghosts.size()-1;
1599  while(abs(jump) > 0){
1600  Mortontry = ghosts[idxtry].computeMorton();
1601  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
1602  idxtry += jump;
1603  if (idxtry > ghosts.size()-1){
1604  if (jump > 0){
1605  idxtry = ghosts.size() - 1;
1606  jump = 0;
1607  }
1608  else if (jump < 0){
1609  idxtry = 0;
1610  jump = 0;
1611  }
1612  }
1613  }
1614  if(ghosts[idxtry].computeMorton() == Morton && ghosts[idxtry].level == oct->level){
1615  //Found neighbour of same size
1616  isghost.push_back(true);
1617  neighbours.push_back(idxtry);
1618  return;
1619  }
1620  else{
1621  // Step until the mortontry lower than morton (one idx of distance)
1622  {
1623  while(ghosts[idxtry].computeMorton() < Morton){
1624  idxtry++;
1625  if(idxtry > ghosts.size()-1){
1626  idxtry = ghosts.size()-1;
1627  break;
1628  }
1629  }
1630  while(ghosts[idxtry].computeMorton() > Morton){
1631  idxtry--;
1632  if(idxtry > ghosts.size()-1){
1633  idxtry = 0;
1634  break;
1635  }
1636  }
1637  }
1638  if(idxtry < size_ghosts){
1639  if(ghosts[idxtry].computeMorton() == Morton && ghosts[idxtry].level == oct->level){
1640  //Found neighbour of same size
1641  isghost.push_back(true);
1642  neighbours.push_back(idxtry);
1643  return;
1644  }
1645  // Compute Last discendent of virtual octant of same size
1646  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
1647  uint64_t Mortonlast = last_desc.computeMorton();
1648  Mortontry = ghosts[idxtry].computeMorton();
1649  int32_t Dx, Dy;
1650  int32_t Dxstar, Dystar;
1651  while(Mortontry < Mortonlast && idxtry < size_ghosts){
1652  Dx = int32_t(abs(cx))*(-int32_t(oct->x) + int32_t(ghosts[idxtry].x));
1653  Dy = int32_t(abs(cy))*(-int32_t(oct->y) + int32_t(ghosts[idxtry].y));
1654  Dxstar = int32_t((cx-1)/2)*(ghosts[idxtry].getSize()) + int32_t((cx+1)/2)*size;
1655  Dystar = int32_t((cy-1)/2)*(ghosts[idxtry].getSize()) + int32_t((cy+1)/2)*size;
1656 
1657  uint32_t x0 = oct->x;
1658  uint32_t x1 = x0 + size;
1659  uint32_t y0 = oct->y;
1660  uint32_t y1 = y0 + size;
1661  uint32_t x0try = ghosts[idxtry].x;
1662  uint32_t x1try = x0try + ghosts[idxtry].getSize();
1663  uint32_t y0try = ghosts[idxtry].y;
1664  uint32_t y1try = y0try + ghosts[idxtry].getSize();
1665  uint8_t level = oct->level;
1666  uint8_t leveltry = ghosts[idxtry].getLevel();
1667 
1668  if (Dx == Dxstar && Dy == Dystar){
1669  if (leveltry > level){
1670  if((abs(cx)*((y0try>=y0)*(y0try<y1))) + (abs(cy)*((x0try>=x0)*(x0try<x1)))){
1671  neighbours.push_back(idxtry);
1672  isghost.push_back(true);
1673  }
1674  }
1675  if (leveltry < level){
1676  if((abs(cx)*((y0>=y0try)*(y0<y1try))) + (abs(cy)*((x0>=x0try)*(x0<x1try)))){
1677  neighbours.push_back(idxtry);
1678  isghost.push_back(true);
1679  }
1680  }
1681  }
1682 
1683  idxtry++;
1684  if(idxtry>size_ghosts-1){
1685  break;
1686  }
1687  Mortontry = ghosts[idxtry].computeMorton();
1688  }
1689  }
1690  }
1691 
1692  uint32_t lengthneigh = 0;
1693  uint32_t sizeneigh = neighbours.size();
1694  for (idxtry=0; idxtry<sizeneigh; idxtry++){
1695  lengthneigh += ghosts[neighbours[idxtry]].getSize();
1696  }
1697  if (lengthneigh < oct->getSize()){
1698  // Search in octants
1699 
1700  // Check if octants face is a boundary
1701  if (oct->info[iface] == false){
1702 
1703  //Build Morton number of virtual neigh of same size
1704  Class_Octant<2> samesizeoct(oct->level, oct->x+cx*size, oct->y+cy*size);
1705  Morton = samesizeoct.computeMorton();
1706  // Search morton in octants
1707  // If a even face morton is lower than morton of oct, if odd higher
1708  // ---> can i search only before or after idx in octants
1709  int32_t jump = (oct->computeMorton() > Morton) ? int32_t(idx/2+1) : int32_t((noctants -idx)/2+1);
1710  idxtry = uint32_t(idx +((oct->computeMorton()<Morton)-(oct->computeMorton()>Morton))*jump);
1711  if (idxtry > noctants-1) idxtry = noctants-1;
1712  while(abs(jump) > 0){
1713  Mortontry = octants[idxtry].computeMorton();
1714  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
1715  idxtry += jump;
1716  if (idxtry > noctants-1){
1717  if (jump > 0){
1718  idxtry = noctants - 1;
1719  jump = 0;
1720  }
1721  else if (jump < 0){
1722  idxtry = 0;
1723  jump = 0;
1724  }
1725  }
1726  }
1727  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
1728  //Found neighbour of same size
1729  isghost.push_back(false);
1730  neighbours.push_back(idxtry);
1731  return;
1732  }
1733  else{
1734  // Step until the mortontry lower than morton (one idx of distance)
1735  {
1736  while(octants[idxtry].computeMorton() < Morton){
1737  idxtry++;
1738  if(idxtry > noctants-1){
1739  idxtry = noctants-1;
1740  break;
1741  }
1742  }
1743  while(octants[idxtry].computeMorton() > Morton){
1744  idxtry--;
1745  if(idxtry > noctants-1){
1746  idxtry = 0;
1747  break;
1748  }
1749  }
1750  }
1751  if (idxtry < noctants){
1752  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
1753  //Found neighbour of same size
1754  isghost.push_back(false);
1755  neighbours.push_back(idxtry);
1756  return;
1757  }
1758  // Compute Last discendent of virtual octant of same size
1759  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
1760  uint64_t Mortonlast = last_desc.computeMorton();
1761  Mortontry = octants[idxtry].computeMorton();
1762  int32_t Dx, Dy;
1763  int32_t Dxstar, Dystar;
1764  while(Mortontry < Mortonlast && idxtry <= noctants-1){
1765  Dx = int32_t(abs(cx))*(-int32_t(oct->x) + int32_t(octants[idxtry].x));
1766  Dy = int32_t(abs(cy))*(-int32_t(oct->y) + int32_t(octants[idxtry].y));
1767  Dxstar = int32_t((cx-1)/2)*(octants[idxtry].getSize()) + int32_t((cx+1)/2)*size;
1768  Dystar = int32_t((cy-1)/2)*(octants[idxtry].getSize()) + int32_t((cy+1)/2)*size;
1769 
1770  uint32_t x0 = oct->x;
1771  uint32_t x1 = x0 + size;
1772  uint32_t y0 = oct->y;
1773  uint32_t y1 = y0 + size;
1774  uint32_t x0try = octants[idxtry].x;
1775  uint32_t x1try = x0try + octants[idxtry].getSize();
1776  uint32_t y0try = octants[idxtry].y;
1777  uint32_t y1try = y0try + octants[idxtry].getSize();
1778  uint8_t level = oct->level;
1779  uint8_t leveltry = octants[idxtry].getLevel();
1780 
1781  if (Dx == Dxstar && Dy == Dystar){
1782  if (leveltry > level){
1783  if((abs(cx)*((y0try>=y0)*(y0try<y1))) + (abs(cy)*((x0try>=x0)*(x0try<x1)))){
1784  neighbours.push_back(idxtry);
1785  isghost.push_back(false);
1786  }
1787  }
1788  if (leveltry < level){
1789  if((abs(cx)*((y0>=y0try)*(y0<y1try))) + (abs(cy)*((x0>=x0try)*(x0<x1try)))){
1790  neighbours.push_back(idxtry);
1791  isghost.push_back(false);
1792  }
1793  }
1794  }
1795 
1796  idxtry++;
1797  if(idxtry>noctants-1){
1798  break;
1799  }
1800  Mortontry = octants[idxtry].computeMorton();
1801  }
1802  }
1803  }
1804  }
1805  }
1806  return;
1807  }
1808  }
1809  else{
1810  // Boundary Face
1811  return;
1812  }
1813  }
1814  };
1815 
1816  // =================================================================================== //
1817 
1818  void findNeighbours(Class_Octant<2> *oct, // Finds neighbours of octant through iface in vector octants.
1819  uint8_t iface, // Returns a vector (empty if iface is a bound face) with the index of neighbours
1820  u32vector & neighbours, // in their structure (octants or ghosts) and sets isghost[i] = true if the
1821  vector<bool> & isghost){ // i-th neighbour is ghost in the local tree
1822 
1823  uint64_t Morton, Mortontry;
1824  uint32_t noctants = getNumOctants();
1825  uint32_t idxtry;
1826  uint32_t size = oct->getSize();
1827 
1828  // TODO Create a global matrix
1829  //Alternative to switch case
1830  int8_t cx = int8_t((iface<2)*(int8_t(2*iface-1)));
1831  int8_t cy = int8_t((int8_t(iface/2))*(int8_t(2*iface-5)));
1832 
1833  isghost.clear();
1834  neighbours.clear();
1835 
1836  // Default if iface is nface<iface<0
1837  if (iface < 0 || iface > global2D.nfaces){
1838  return;
1839  }
1840 
1841  // Check if octants face is a process boundary
1842  if (oct->info[global2D.nfaces+iface] == false){
1843 
1844  // Check if octants face is a boundary
1845  if (oct->info[iface] == false){
1846 
1847  //Build Morton number of virtual neigh of same size
1848  Class_Octant<2> samesizeoct(oct->level, int32_t(oct->x)+int32_t(cx*size), int32_t(oct->y)+int32_t(cy*size));
1849  Morton = samesizeoct.computeMorton();
1850  // Search morton in octants
1851  // If a even face morton is lower than morton of oct, if odd higher
1852  // ---> can i search only before or after idx in octants
1853  int32_t jump = int32_t((noctants)/2+1);
1854  idxtry = uint32_t(jump);
1855  Mortontry = oct->computeMorton();
1856  while(abs(jump) > 0){
1857  Mortontry = octants[idxtry].computeMorton();
1858  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
1859  idxtry += jump;
1860  if (idxtry > noctants-1){
1861  if (jump > 0){
1862  idxtry = noctants - 1;
1863  jump = 0;
1864  }
1865  else if (jump < 0){
1866  idxtry = 0;
1867  jump = 0;
1868  }
1869  }
1870  }
1871  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
1872  //Found neighbour of same size
1873  isghost.push_back(false);
1874  neighbours.push_back(idxtry);
1875  return;
1876  }
1877  else{
1878  // Step until the mortontry lower than morton (one idx of distance)
1879  {
1880  while(octants[idxtry].computeMorton() < Morton){
1881  idxtry++;
1882  if(idxtry > noctants-1){
1883  idxtry = noctants-1;
1884  break;
1885  }
1886  }
1887  while(octants[idxtry].computeMorton() > Morton){
1888  idxtry--;
1889  if(idxtry > noctants-1){
1890  idxtry = 0;
1891  break;
1892  }
1893  }
1894  }
1895  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
1896  //Found neighbour of same size
1897  isghost.push_back(false);
1898  neighbours.push_back(idxtry);
1899  return;
1900  }
1901  // Compute Last discendent of virtual octant of same size
1902  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
1903  uint64_t Mortonlast = last_desc.computeMorton();
1904  Mortontry = octants[idxtry].computeMorton();
1905  int32_t Dx, Dy;
1906  int32_t Dxstar, Dystar;
1907  while(Mortontry < Mortonlast && idxtry < noctants){
1908  Dx = int32_t(abs(cx))*(-int32_t(oct->x) + int32_t(octants[idxtry].x));
1909  Dy = int32_t(abs(cy))*(-int32_t(oct->y) + int32_t(octants[idxtry].y));
1910  Dxstar = int32_t((cx-1)/2)*(octants[idxtry].getSize()) + int32_t((cx+1)/2)*size;
1911  Dystar = int32_t((cy-1)/2)*(octants[idxtry].getSize()) + int32_t((cy+1)/2)*size;
1912 
1913  uint32_t x0 = oct->x;
1914  uint32_t x1 = x0 + size;
1915  uint32_t y0 = oct->y;
1916  uint32_t y1 = y0 + size;
1917  uint32_t x0try = octants[idxtry].x;
1918  uint32_t x1try = x0try + octants[idxtry].getSize();
1919  uint32_t y0try = octants[idxtry].y;
1920  uint32_t y1try = y0try + octants[idxtry].getSize();
1921  uint8_t level = oct->level;
1922  uint8_t leveltry = octants[idxtry].getLevel();
1923 
1924  if (Dx == Dxstar && Dy == Dystar){
1925  if (leveltry > level){
1926  if((abs(cx)*((y0try>=y0)*(y0try<y1))) + (abs(cy)*((x0try>=x0)*(x0try<x1)))){
1927  neighbours.push_back(idxtry);
1928  isghost.push_back(false);
1929  }
1930  }
1931  if (leveltry < level){
1932  if((abs(cx)*((y0>=y0try)*(y0<y1try))) + (abs(cy)*((x0>=x0try)*(x0<x1try)))){
1933  neighbours.push_back(idxtry);
1934  isghost.push_back(false);
1935  }
1936  }
1937  }
1938 
1939  idxtry++;
1940  if(idxtry>noctants-1){
1941  break;
1942  }
1943  Mortontry = octants[idxtry].computeMorton();
1944  }
1945  return;
1946  }
1947  }
1948  else{
1949  // Boundary Face
1950  return;
1951  }
1952  }
1953  //--------------------------------------------------------------- //
1954  //--------------------------------------------------------------- //
1955  else{
1956  // Check if octants face is a boundary
1957  if (oct->info[iface] == false){
1958  // IF OCTANT FACE IS A PROCESS BOUNDARY SEARCH ALSO IN GHOSTS
1959 
1960  if (ghosts.size()>0){
1961  // Search in ghosts
1962 
1963  uint32_t idxghost = uint32_t(size_ghosts/2);
1964  Class_Octant<2>* octghost = &ghosts[idxghost];
1965 
1966  //Build Morton number of virtual neigh of same size
1967  Class_Octant<2> samesizeoct(oct->level, oct->x+cx*size, oct->y+cy*size);
1968  Morton = samesizeoct.computeMorton(); //mortonEncode_magicbits(oct->x-size,oct->y,oct->z);
1969  // Search morton in octants
1970  // If a even face morton is lower than morton of oct, if odd higher
1971  // ---> can i search only before or after idx in octants
1972  int32_t jump = (octghost->computeMorton() > Morton) ? int32_t(idxghost/2+1) : int32_t((size_ghosts -idxghost)/2+1);
1973  idxtry = uint32_t(idxghost +((octghost->computeMorton()<Morton)-(octghost->computeMorton()>Morton))*jump);
1974  while(abs(jump) > 0){
1975  Mortontry = ghosts[idxtry].computeMorton();
1976  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
1977  idxtry += jump;
1978  if (idxtry > ghosts.size()-1){
1979  if (jump > 0){
1980  idxtry = ghosts.size() - 1;
1981  jump = 0;
1982  }
1983  else if (jump < 0){
1984  idxtry = 0;
1985  jump = 0;
1986  }
1987  }
1988  }
1989  if(ghosts[idxtry].computeMorton() == Morton && ghosts[idxtry].level == oct->level){
1990  //Found neighbour of same size
1991  isghost.push_back(true);
1992  neighbours.push_back(idxtry);
1993  return;
1994  }
1995  else{
1996  // Step until the mortontry lower than morton (one idx of distance)
1997  {
1998  while(ghosts[idxtry].computeMorton() < Morton){
1999  idxtry++;
2000  if(idxtry > ghosts.size()-1){
2001  idxtry = ghosts.size()-1;
2002  break;
2003  }
2004  }
2005  while(ghosts[idxtry].computeMorton() > Morton){
2006  idxtry--;
2007  if(idxtry > ghosts.size()-1){
2008  idxtry = 0;
2009  break;
2010  }
2011  }
2012  }
2013  if(idxtry < size_ghosts){
2014  if(ghosts[idxtry].computeMorton() == Morton && ghosts[idxtry].level == oct->level){
2015  //Found neighbour of same size
2016  isghost.push_back(true);
2017  neighbours.push_back(idxtry);
2018  return;
2019  }
2020  // Compute Last discendent of virtual octant of same size
2021  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
2022  uint64_t Mortonlast = last_desc.computeMorton();
2023  Mortontry = ghosts[idxtry].computeMorton();
2024  int32_t Dx, Dy;
2025  int32_t Dxstar, Dystar;
2026  while(Mortontry < Mortonlast && idxtry < size_ghosts){
2027  Dx = int32_t(abs(cx))*(-int32_t(oct->x) + int32_t(ghosts[idxtry].x));
2028  Dy = int32_t(abs(cy))*(-int32_t(oct->y) + int32_t(ghosts[idxtry].y));
2029  Dxstar = int32_t((cx-1)/2)*(ghosts[idxtry].getSize()) + int32_t((cx+1)/2)*size;
2030  Dystar = int32_t((cy-1)/2)*(ghosts[idxtry].getSize()) + int32_t((cy+1)/2)*size;
2031 
2032  uint32_t x0 = oct->x;
2033  uint32_t x1 = x0 + size;
2034  uint32_t y0 = oct->y;
2035  uint32_t y1 = y0 + size;
2036  uint32_t x0try = ghosts[idxtry].x;
2037  uint32_t x1try = x0try + ghosts[idxtry].getSize();
2038  uint32_t y0try = ghosts[idxtry].y;
2039  uint32_t y1try = y0try + ghosts[idxtry].getSize();
2040  uint8_t level = oct->level;
2041  uint8_t leveltry = ghosts[idxtry].getLevel();
2042 
2043  if (Dx == Dxstar && Dy == Dystar){
2044  if (leveltry > level){
2045  if((abs(cx)*((y0try>=y0)*(y0try<y1))) + (abs(cy)*((x0try>=x0)*(x0try<x1)))){
2046  neighbours.push_back(idxtry);
2047  isghost.push_back(true);
2048  }
2049  }
2050  if (leveltry < level){
2051  if((abs(cx)*((y0>=y0try)*(y0<y1try))) + (abs(cy)*((x0>=x0try)*(x0<x1try)))){
2052  neighbours.push_back(idxtry);
2053  isghost.push_back(true);
2054  }
2055  }
2056 
2057  }
2058 
2059  idxtry++;
2060  if(idxtry>size_ghosts-1){
2061  break;
2062  }
2063  Mortontry = ghosts[idxtry].computeMorton();
2064  }
2065  }
2066  }
2067 
2068  uint32_t lengthneigh = 0;
2069  uint32_t sizeneigh = neighbours.size();
2070  for (idxtry=0; idxtry<sizeneigh; idxtry++){
2071  lengthneigh += ghosts[neighbours[idxtry]].getSize();
2072  }
2073  if (lengthneigh < oct->getSize()){
2074  // Search in octants
2075 
2076  // Check if octants face is a boundary
2077  if (oct->info[iface] == false){
2078 
2079  //Build Morton number of virtual neigh of same size
2080  Class_Octant<2> samesizeoct(oct->level, oct->x+cx*size, oct->y+cy*size);
2081  Morton = samesizeoct.computeMorton();
2082  // Search morton in octants
2083  // If a even face morton is lower than morton of oct, if odd higher
2084  // ---> can i search only before or after idx in octants
2085  int32_t jump = int32_t((noctants)/2+1);
2086  idxtry = uint32_t(jump);
2087  while(abs(jump) > 0){
2088  Mortontry = octants[idxtry].computeMorton();
2089  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
2090  idxtry += jump;
2091  if (idxtry > noctants-1){
2092  if (jump > 0){
2093  idxtry = noctants - 1;
2094  jump = 0;
2095  }
2096  else if (jump < 0){
2097  idxtry = 0;
2098  jump = 0;
2099  }
2100  }
2101  }
2102  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
2103  //Found neighbour of same size
2104  isghost.push_back(false);
2105  neighbours.push_back(idxtry);
2106  return;
2107  }
2108  else{
2109  // Step until the mortontry lower than morton (one idx of distance)
2110  {
2111  while(octants[idxtry].computeMorton() < Morton){
2112  idxtry++;
2113  if(idxtry > noctants-1){
2114  idxtry = noctants-1;
2115  break;
2116  }
2117  }
2118  while(octants[idxtry].computeMorton() > Morton){
2119  idxtry--;
2120  if(idxtry > noctants-1){
2121  idxtry = 0;
2122  break;
2123  }
2124  }
2125  }
2126  if (idxtry < noctants){
2127  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
2128  //Found neighbour of same size
2129  isghost.push_back(false);
2130  neighbours.push_back(idxtry);
2131  return;
2132  }
2133  // Compute Last discendent of virtual octant of same size
2134  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
2135  uint64_t Mortonlast = last_desc.computeMorton();
2136  Mortontry = octants[idxtry].computeMorton();
2137  int32_t Dx, Dy;
2138  int32_t Dxstar, Dystar;
2139  while(Mortontry < Mortonlast && idxtry <= noctants-1){
2140  Dx = int32_t(abs(cx))*(-int32_t(oct->x) + int32_t(octants[idxtry].x));
2141  Dy = int32_t(abs(cy))*(-int32_t(oct->y) + int32_t(octants[idxtry].y));
2142  Dxstar = int32_t((cx-1)/2)*(octants[idxtry].getSize()) + int32_t((cx+1)/2)*size;
2143  Dystar = int32_t((cy-1)/2)*(octants[idxtry].getSize()) + int32_t((cy+1)/2)*size;
2144 
2145  uint32_t x0 = oct->x;
2146  uint32_t x1 = x0 + size;
2147  uint32_t y0 = oct->y;
2148  uint32_t y1 = y0 + size;
2149  uint32_t x0try = octants[idxtry].x;
2150  uint32_t x1try = x0try + octants[idxtry].getSize();
2151  uint32_t y0try = octants[idxtry].y;
2152  uint32_t y1try = y0try + octants[idxtry].getSize();
2153  uint8_t level = oct->level;
2154  uint8_t leveltry = octants[idxtry].getLevel();
2155 
2156  if (Dx == Dxstar && Dy == Dystar){
2157  if (leveltry > level){
2158  if((abs(cx)*((y0try>=y0)*(y0try<y1))) + (abs(cy)*((x0try>=x0)*(x0try<x1)))){
2159  neighbours.push_back(idxtry);
2160  isghost.push_back(false);
2161  }
2162  }
2163  if (leveltry < level){
2164  if((abs(cx)*((y0>=y0try)*(y0<y1try))) + (abs(cy)*((x0>=x0try)*(x0<x1try)))){
2165  neighbours.push_back(idxtry);
2166  isghost.push_back(false);
2167  }
2168  }
2169  }
2170 
2171  idxtry++;
2172  Mortontry = octants[idxtry].computeMorton();
2173  }
2174  }
2175  }
2176  }
2177  }
2178  return;
2179  }
2180  }
2181  else{
2182  // Boundary Face
2183  return;
2184  }
2185  }
2186  };
2187 
2188  // =================================================================================== //
2189 
2190  void findGhostNeighbours(uint32_t const idx, // Finds neighbours of idx-th ghost octant through iface in vector octants.
2191  uint8_t iface, // Returns a vector (empty if iface is not the pbound face for ghost) with the index of neighbours
2192  u32vector & neighbours){ // in the structure octants
2193 
2194  uint64_t Morton, Mortontry;
2195  uint32_t noctants = getNumOctants();
2196  uint32_t idxtry;
2197  Class_Octant<2>* oct = &ghosts[idx];
2198  uint32_t size = oct->getSize();
2199 
2200  //Alternative to switch case
2201  int8_t cx = int8_t((iface<2)*(int8_t(2*iface-1)));
2202  int8_t cy = int8_t((int8_t(iface/2))*(int8_t(2*iface-5)));
2203 
2204  neighbours.clear();
2205 
2206  // Default if iface is nface<iface<0
2207  if (iface < 0 || iface > global2D.nfaces){
2208  return;
2209  }
2210 
2211  // Check if octants face is a process boundary
2212  if (oct->info[global2D.nfaces+iface] == true){
2213 
2214  //Build Morton number of virtual neigh of same size
2215  Class_Octant<2> samesizeoct(oct->level, int32_t(oct->x)+int32_t(cx*size), int32_t(oct->y)+int32_t(cy*size));
2216  Morton = samesizeoct.computeMorton();
2217  // Search morton in octants
2218  // If a even face morton is lower than morton of oct, if odd higher
2219  // ---> can i search only before or after idx in octants
2220  int32_t jump = getNumOctants()/2;
2221  idxtry = uint32_t(getNumOctants()/2);
2222  Mortontry = octants[idxtry].computeMorton();
2223  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
2224  while(abs(jump) > 0){
2225  Mortontry = octants[idxtry].computeMorton();
2226  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
2227  idxtry += jump;
2228  if (idxtry > noctants-1){
2229  if (jump > 0){
2230  idxtry = noctants - 1;
2231  jump = 0;
2232  }
2233  else if (jump < 0){
2234  idxtry = 0;
2235  jump = 0;
2236  }
2237  }
2238  }
2239  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
2240  //Found neighbour of same size
2241  neighbours.push_back(idxtry);
2242  return;
2243  }
2244  else{
2245  // Step until the mortontry lower than morton (one idx of distance)
2246  {
2247  while(octants[idxtry].computeMorton() < Morton){
2248  idxtry++;
2249  if(idxtry > noctants-1){
2250  idxtry = noctants-1;
2251  break;
2252  }
2253  }
2254  while(octants[idxtry].computeMorton() > Morton){
2255  idxtry--;
2256  if(idxtry > noctants-1){
2257  idxtry = 0;
2258  break;
2259  }
2260  }
2261  }
2262  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
2263  //Found neighbour of same size
2264  neighbours.push_back(idxtry);
2265  return;
2266  }
2267  // Compute Last discendent of virtual octant of same size
2268  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
2269  uint64_t Mortonlast = last_desc.computeMorton();
2270  Mortontry = octants[idxtry].computeMorton();
2271  int32_t Dx, Dy;
2272  int32_t Dxstar, Dystar;
2273  while(Mortontry < Mortonlast && idxtry < noctants){
2274  Dx = int32_t(abs(cx))*(-int32_t(oct->x) + int32_t(octants[idxtry].x));
2275  Dy = int32_t(abs(cy))*(-int32_t(oct->y) + int32_t(octants[idxtry].y));
2276  Dxstar = int32_t((cx-1)/2)*(octants[idxtry].getSize()) + int32_t((cx+1)/2)*size;
2277  Dystar = int32_t((cy-1)/2)*(octants[idxtry].getSize()) + int32_t((cy+1)/2)*size;
2278 
2279  uint32_t x0 = oct->x;
2280  uint32_t x1 = x0 + size;
2281  uint32_t y0 = oct->y;
2282  uint32_t y1 = y0 + size;
2283  uint32_t x0try = octants[idxtry].x;
2284  uint32_t x1try = x0try + octants[idxtry].getSize();
2285  uint32_t y0try = octants[idxtry].y;
2286  uint32_t y1try = y0try + octants[idxtry].getSize();
2287  uint8_t level = oct->level;
2288  uint8_t leveltry = octants[idxtry].getLevel();
2289 
2290  if (Dx == Dxstar && Dy == Dystar){
2291  if (leveltry > level){
2292  if((abs(cx)*((y0try>=y0)*(y0try<y1))) + (abs(cy)*((x0try>=x0)*(x0try<x1)))){
2293  neighbours.push_back(idxtry);
2294  }
2295  }
2296  if (leveltry < level){
2297  if((abs(cx)*((y0>=y0try)*(y0<y1try))) + (abs(cy)*((x0>=x0try)*(x0<x1try)))){
2298  neighbours.push_back(idxtry);
2299  }
2300  }
2301  }
2302 
2303  idxtry++;
2304  if(idxtry>noctants-1){
2305  break;
2306  }
2307  Mortontry = octants[idxtry].computeMorton();
2308  }
2309  return;
2310  }
2311  }
2312  //--------------------------------------------------------------- //
2313  //-----Not Pbound face------------- ----------------------------- //
2314  else{
2315  return;
2316  }
2317  };
2318 
2319  // =================================================================================== //
2320 
2321  void preBalance21(bool internal){
2322  // Local variables
2323  Class_Octant<2> father, lastdesc;
2324  uint64_t mortonld;
2325  uint32_t nocts;
2326  uint32_t idx, idx2, idx0, last_idx;
2327  uint32_t idx1_gh, idx2_gh;
2328  int8_t markerfather, marker;
2329  uint8_t nbro;
2330  uint8_t nchm1 = global2D.nchildren-1;
2331  //bool wstop = false;
2332  bool Bdone=false;
2333 
2334  //------------------------------------------ //
2335  // Initialization
2336 
2337  nbro = 0;
2338  idx2_gh = idx0 = 0;
2339  idx1_gh=0;
2340 
2341  nocts = octants.size();
2342  size_ghosts = ghosts.size();
2343  last_idx=nocts-1;
2344 
2345  //Clean index of ghost brothers in case of coarsening a broken family
2346  last_ghost_bros.clear();
2347 
2348  // Set index for start and end check for ghosts
2349  if (ghosts.size()){
2350  while(idx2_gh < size_ghosts && ghosts[idx2_gh].computeMorton() <= last_desc.computeMorton()){
2351  idx2_gh++;
2352  }
2353  idx2_gh = min((size_ghosts-1), idx2_gh);
2354 
2355  while(idx1_gh < size_ghosts && ghosts[idx1_gh].computeMorton() <= octants[0].computeMorton()){
2356  idx1_gh++;
2357  }
2358  idx1_gh-=1;
2359  if (idx1_gh==-1) idx1_gh=0;
2360  }
2361 
2362  // End on ghosts
2363  if (ghosts.size() && nocts > 0){
2364  if (ghosts[idx1_gh].buildFather()==octants[0].buildFather()){
2365  father = ghosts[idx1_gh].buildFather();
2366  nbro = 0;
2367  idx = idx1_gh;
2368  marker = ghosts[idx].getMarker();
2369  while(marker < 0 && ghosts[idx].buildFather() == father){
2370  nbro++;
2371  if (idx==0)
2372  break;
2373  idx--;
2374  marker = ghosts[idx].getMarker();
2375  }
2376  idx = 0;
2377  //marker = octants[idx].getMarker();
2378  //while(marker<0 && octants[idx].buildFather() == father){
2379  while(octants[idx].buildFather() == father){
2380  if (octants[idx].getMarker()<0)
2381  nbro++;
2382  idx++;
2383  if (idx==nocts)
2384  break;
2385  }
2386  if (nbro != global2D.nchildren && idx!=nocts-1){
2387  for(uint32_t ii=0; ii<idx; ii++){
2388  if(octants[ii].getMarker()<0){
2389  octants[ii].setMarker(0);
2390  octants[ii].info[11]=true;
2391  Bdone=true;
2392  }
2393  }
2394  }
2395  }
2396 
2397  //if ((ghosts[idx2_gh].getMarker() < 0) && (octants[nocts-1].getMarker() < 0)){
2398  if (ghosts[idx2_gh].buildFather()==octants[nocts-1].buildFather()){
2399  father = ghosts[idx2_gh].buildFather();
2400  nbro = 0;
2401  idx = idx2_gh;
2402  marker = ghosts[idx].getMarker();
2403  while(marker < 0 && ghosts[idx].buildFather() == father){
2404 
2405  //Add ghost index to structure for mapper in case of coarsening a broken family
2406  last_ghost_bros.push_back(idx);
2407 
2408  nbro++;
2409  idx++;
2410  if(idx == size_ghosts){
2411  break;
2412  }
2413  marker = ghosts[idx].getMarker();
2414  }
2415  idx = nocts-1;
2416  //marker = octants[idx].getMarker();
2417  //while(marker<0 && octants[idx].buildFather() == father && idx >= 0){
2418  // nbro++;
2419  while(octants[idx].buildFather() == father){
2420  if (octants[idx].getMarker()<0)
2421  nbro++;
2422  if (idx==0)
2423  break;
2424  idx--;
2425  }
2426  last_idx=idx;
2427  if (nbro != global2D.nchildren && idx!=nocts-1){
2428  for(uint32_t ii=idx+1; ii<nocts; ii++){
2429  if (octants[ii].getMarker()<0){
2430  octants[ii].setMarker(0);
2431  octants[ii].info[11]=true;
2432  Bdone=true;
2433  }
2434  }
2435  //Clean ghost index to structure for mapper in case of coarsening a broken family
2436  last_ghost_bros.clear();
2437  }
2438  }
2439  }
2440 
2441  // Check first internal octants
2442  if (internal){
2443  father = octants[0].buildFather();
2444  lastdesc = father.buildLastDesc();
2445  mortonld = lastdesc.computeMorton();
2446  nbro = 0;
2447  for (idx=0; idx<global2D.nchildren; idx++){
2448  // Check if family is complete or to be checked in the internal loop (some brother refined)
2449  if (octants[idx].computeMorton() <= mortonld){
2450  nbro++;
2451  }
2452  }
2453  if (nbro != global2D.nchildren)
2454  idx0 = nbro;
2455 
2456  // Check and coarse internal octants
2457  for (idx=idx0; idx<nocts; idx++){
2458  if(octants[idx].getMarker() < 0 && octants[idx].getLevel() > 0){
2459  nbro = 0;
2460  father = octants[idx].buildFather();
2461  // Check if family is to be coarsened
2462  for (idx2=idx; idx2<idx+global2D.nchildren; idx2++){
2463  if (idx2<nocts){
2464  if(octants[idx2].getMarker() < 0 && octants[idx2].buildFather() == father){
2465  nbro++;
2466  }
2467  }
2468  }
2469  if (nbro == global2D.nchildren){
2470  idx = idx2-1;
2471  }
2472  else{
2473  if (idx<=last_idx){
2474  octants[idx].setMarker(0);
2475  octants[idx].info[11]=true;
2476  Bdone=true;
2477  }
2478  }
2479  }
2480  }
2481  }
2482  };
2483 
2484  // =================================================================================== //
2485 
2486  void preBalance21(u32vector& newmodified){
2487  // Local variables
2488  Class_Octant<2> father, lastdesc;
2489  uint64_t mortonld;
2490  uint32_t nocts;
2491  uint32_t idx, idx2, idx0, last_idx;
2492  uint32_t idx1_gh, idx2_gh;
2493  int8_t markerfather, marker;
2494  uint8_t nbro;
2495  uint8_t nchm1 = global2D.nchildren-1;
2496  bool Bdone=false;
2497 
2498  //------------------------------------------ //
2499  // Initialization
2500 
2501  nbro = 0;
2502  idx2_gh = idx0 = 0;
2503  idx1_gh=0;
2504 
2505  nocts = octants.size();
2506  size_ghosts = ghosts.size();
2507  last_idx=nocts-1;
2508 
2509  //Clean index of ghost brothers in case of coarsening a broken family
2510  last_ghost_bros.clear();
2511 
2512  // Set index for start and end check for ghosts
2513  if (ghosts.size()){
2514  while(idx2_gh < size_ghosts && ghosts[idx2_gh].computeMorton() <= last_desc.computeMorton()){
2515  idx2_gh++;
2516  }
2517  idx2_gh = min((size_ghosts-1), idx2_gh);
2518 
2519  while(idx1_gh < size_ghosts && ghosts[idx1_gh].computeMorton() <= octants[0].computeMorton()){
2520  idx1_gh++;
2521  }
2522  idx1_gh-=1;
2523  if (idx1_gh==-1) idx1_gh=0;
2524  }
2525 
2526  // End on ghosts
2527  if (ghosts.size() && nocts > 0){
2528  if (ghosts[idx1_gh].buildFather()==octants[0].buildFather()){
2529  father = ghosts[idx1_gh].buildFather();
2530  nbro = 0;
2531  idx = idx1_gh;
2532  marker = ghosts[idx].getMarker();
2533  while(marker < 0 && ghosts[idx].buildFather() == father){
2534 
2535  //Add ghost index to structure for mapper in case of coarsening a broken family
2536  last_ghost_bros.push_back(idx);
2537 
2538  nbro++;
2539  if (idx==0)
2540  break;
2541  idx--;
2542  marker = ghosts[idx].getMarker();
2543  }
2544  idx = 0;
2545  //marker = octants[idx].getMarker();
2546  //while(marker<0 && octants[idx].buildFather() == father){
2547  while(idx<nocts && octants[idx].buildFather() == father){
2548  if (octants[idx].getMarker()<0)
2549  nbro++;
2550  idx++;
2551  if(idx==nocts)
2552  break;
2553  }
2554  if (nbro != global2D.nchildren && idx!=nocts-1){
2555  for(uint32_t ii=0; ii<idx; ii++){
2556  if (octants[ii].getMarker()<0){
2557  octants[ii].setMarker(0);
2558  octants[ii].info[11]=true;
2559  Bdone=true;
2560  newmodified.push_back(ii);
2561  }
2562  }
2563  //Clean index of ghost brothers in case of coarsening a broken family
2564  last_ghost_bros.clear();
2565  }
2566  }
2567 
2568  //if ((ghosts[idx2_gh].getMarker() < 0) && (octants[nocts-1].getMarker() < 0)){
2569  if (ghosts[idx2_gh].buildFather()==octants[nocts-1].buildFather()){
2570  father = ghosts[idx2_gh].buildFather();
2571  nbro = 0;
2572  idx = idx2_gh;
2573  marker = ghosts[idx].getMarker();
2574  while(marker < 0 && ghosts[idx].buildFather() == father){
2575  nbro++;
2576  idx++;
2577  if(idx == size_ghosts){
2578  break;
2579  }
2580  marker = ghosts[idx].getMarker();
2581  }
2582  idx = nocts-1;
2583  //marker = octants[idx].getMarker();
2584  //while(marker<0 && octants[idx].buildFather() == father && idx >= 0){
2585  while(octants[idx].buildFather() == father){
2586  if (octants[idx].getMarker()<0)
2587  nbro++;
2588  idx--;
2589  if (idx==0)
2590  break;
2591  }
2592  last_idx=idx;
2593  if (nbro != global2D.nchildren && idx!=nocts-1){
2594  for(uint32_t ii=idx+1; ii<nocts; ii++){
2595  if (octants[ii].getMarker()<0){
2596  octants[ii].setMarker(0);
2597  octants[ii].info[11]=true;
2598  Bdone=true;
2599  newmodified.push_back(ii);
2600  }
2601  }
2602  }
2603  }
2604  }
2605 
2606  // Check first internal octants
2607  father = octants[0].buildFather();
2608  lastdesc = father.buildLastDesc();
2609  mortonld = lastdesc.computeMorton();
2610  nbro = 0;
2611  for (idx=0; idx<global2D.nchildren; idx++){
2612  // Check if family is complete or to be checked in the internal loop (some brother refined)
2613  if (octants[idx].computeMorton() <= mortonld){
2614  nbro++;
2615  }
2616  }
2617  if (nbro != global2D.nchildren)
2618  idx0 = nbro;
2619 
2620  // Check and coarse internal octants
2621  for (idx=idx0; idx<nocts; idx++){
2622  if(octants[idx].getMarker() < 0 && octants[idx].getLevel() > 0){
2623  nbro = 0;
2624  father = octants[idx].buildFather();
2625  // Check if family is to be coarsened
2626  for (idx2=idx; idx2<idx+global2D.nchildren; idx2++){
2627  if (idx2<nocts){
2628  if(octants[idx2].getMarker() < 0 && octants[idx2].buildFather() == father){
2629  nbro++;
2630  }
2631  }
2632  }
2633  if (nbro == global2D.nchildren){
2634  idx = idx2-1;
2635  }
2636  else{
2637  if (idx<=last_idx){
2638  octants[idx].setMarker(0);
2639  octants[idx].info[11]=true;
2640  Bdone=true;
2641  newmodified.push_back(idx);
2642  }
2643  }
2644  }
2645  }
2646  };
2647 
2648  // =================================================================================== //
2649 
2650  bool localBalance(bool doInterior){ // 2:1 balancing on level a local tree already adapted (balance only the octants with info[14] = false) (refinement wins!)
2651  // Return true if balanced done with some markers modification
2652  // Seto doInterior = false if the interior octants are already balanced
2653  // Local variables
2654  uint32_t sizeneigh, modsize;
2655  u32vector neigh;
2656  u32vector modified, newmodified;
2657  uint32_t i, idx;
2658  uint8_t iface, inode;
2659  int8_t targetmarker;
2660  vector<bool> isghost;
2661  bool Bdone = false;
2662 
2663  OctantsType::iterator obegin, oend, it;
2664  u32vector::iterator ibegin, iend, iit;
2665 
2666  //If interior octants have to be balanced
2667  if(doInterior){
2668  obegin = octants.begin();
2669  oend = octants.end();
2670  idx = 0;
2671  for (it=obegin; it!=oend; it++){
2672  if (!it->getNotBalance() && it->getMarker() != 0){
2673  targetmarker = min(MAX_LEVEL_2D, int(octants[idx].getLevel()) + int(octants[idx].getMarker()));
2674 
2675  //Balance through faces
2676  for (iface=0; iface<global2D.nfaces; iface++){
2677  if(!it->getBound(iface)){
2678  findNeighbours(idx, iface, neigh, isghost);
2679  sizeneigh = neigh.size();
2680  for(i=0; i<sizeneigh; i++){
2681  if (!isghost[i]){
2682  {
2683  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1) ){
2684  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-1-octants[idx].getLevel());
2685  octants[idx].info[11] = true;
2686  modified.push_back(idx);
2687  Bdone = true;
2688  }
2689  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2690  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2691  octants[neigh[i]].info[11] = true;
2692  modified.push_back(neigh[i]);
2693  Bdone = true;
2694  }
2695  };
2696  }
2697  else{
2698  if((ghosts[neigh[i]].getLevel() + ghosts[neigh[i]].getMarker()) > (targetmarker + 1) ){
2699  octants[idx].setMarker(ghosts[neigh[i]].getLevel()+ghosts[neigh[i]].getMarker()-1-octants[idx].getLevel());
2700  octants[idx].info[11] = true;
2701  modified.push_back(idx);
2702  Bdone = true;
2703  }
2704  }
2705  }
2706  }
2707  }
2708 
2709  if (balance_codim>1){
2710  //Balance through nodes
2711  for (inode=0; inode<global2D.nnodes; inode++){
2712  if(!it->getBound(global2D.nodeface[inode][0]) && !it->getBound(global2D.nodeface[inode][1])){
2713  findNodeNeighbours(idx, inode, neigh, isghost);
2714  sizeneigh = neigh.size();
2715  for(i=0; i<sizeneigh; i++){
2716  if (!isghost[i]){
2717  {
2718  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1) ){
2719  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-1-octants[idx].getLevel());
2720  octants[idx].info[11] = true;
2721  modified.push_back(idx);
2722  Bdone = true;
2723  }
2724  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2725  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2726  octants[neigh[i]].info[11] = true;
2727  modified.push_back(neigh[i]);
2728  Bdone = true;
2729  }
2730  };
2731  }
2732  else{
2733  if((ghosts[neigh[i]].getLevel() + ghosts[neigh[i]].getMarker()) > (targetmarker + 1) ){
2734  octants[idx].setMarker(ghosts[neigh[i]].getLevel()+ghosts[neigh[i]].getMarker()-1-octants[idx].getLevel());
2735  octants[idx].info[11] = true;
2736  modified.push_back(idx);
2737  Bdone = true;
2738  }
2739  }
2740  }
2741  }
2742  }
2743  }
2744 
2745  }
2746  idx++;
2747  }
2748 
2749  // Loop on ghost octants (influence over interior borders)
2750  obegin = ghosts.begin();
2751  oend = ghosts.end();
2752  idx = 0;
2753  for (it=obegin; it!=oend; it++){
2754  if (!it->getNotBalance() && it->getMarker() != 0){
2755  targetmarker = min(MAX_LEVEL_2D, (it->getLevel()+it->getMarker()));
2756 
2757  //Balance through faces
2758  for (iface=0; iface<global2D.nfaces; iface++){
2759  if(it->getPbound(iface) == true){
2760  neigh.clear();
2761  findGhostNeighbours(idx, iface, neigh);
2762  sizeneigh = neigh.size();
2763  for(i=0; i<sizeneigh; i++){
2764  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2765  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2766  octants[neigh[i]].info[11] = true;
2767  modified.push_back(neigh[i]);
2768  Bdone = true;
2769  }
2770  }
2771  }
2772  }
2773 
2774  if (balance_codim>1){
2775  //Balance through nodes
2776  for (inode=0; inode<global2D.nnodes; inode++){
2777  if(it->getPbound(global2D.nodeface[inode][0]) == true || it->getPbound(global2D.nodeface[inode][1]) == true){
2778  neigh.clear();
2779  findGhostNodeNeighbours(idx, inode, neigh);
2780  sizeneigh = neigh.size();
2781  for(i=0; i<sizeneigh; i++){
2782  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2783  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2784  octants[neigh[i]].info[11] = true;
2785  modified.push_back(neigh[i]);
2786  Bdone = true;
2787  }
2788  }
2789  }
2790  }
2791  }
2792 
2793  }
2794  idx++;
2795  }
2796 
2797  // While loop for iterative balancing
2798  u32vector().swap(newmodified);
2799  modsize = modified.size();
2800  while(modsize!=0){
2801  ibegin = modified.begin();
2802  iend = modified.end();
2803  for (iit=ibegin; iit!=iend; iit++){
2804  idx = *iit;
2805  if (!octants[idx].getNotBalance()){
2806  targetmarker = min(MAX_LEVEL_2D, (octants[idx].getLevel()+octants[idx].getMarker()));
2807 
2808  //Balance through faces
2809  for (iface=0; iface<global2D.nfaces; iface++){
2810  if(!octants[idx].getPbound(iface)){
2811  findNeighbours(idx, iface, neigh, isghost);
2812  sizeneigh = neigh.size();
2813  for(i=0; i<sizeneigh; i++){
2814  if (!isghost[i]){
2815  {
2816  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1)){
2817  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-octants[idx].getLevel()-1);
2818  octants[idx].info[11] = true;
2819  newmodified.push_back(idx);
2820  Bdone = true;
2821  }
2822  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2823  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2824  octants[neigh[i]].info[11] = true;
2825  newmodified.push_back(neigh[i]);
2826  Bdone = true;
2827  }
2828  };
2829  }
2830  }
2831  }
2832  }
2833 
2834  if (balance_codim>1){
2835  //Balance through nodes
2836  for (inode=0; inode<global2D.nnodes; inode++){
2837  if(!octants[idx].getPbound(global2D.nodeface[inode][0]) || !octants[idx].getPbound(global2D.nodeface[inode][1])){
2838  findNodeNeighbours(idx, inode, neigh, isghost);
2839  sizeneigh = neigh.size();
2840  for(i=0; i<sizeneigh; i++){
2841  if (!isghost[i]){
2842  {
2843  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1)){
2844  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-octants[idx].getLevel()-1);
2845  octants[idx].info[11] = true;
2846  newmodified.push_back(idx);
2847  Bdone = true;
2848  }
2849  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2850  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2851  octants[neigh[i]].info[11] = true;
2852  newmodified.push_back(neigh[i]);
2853  Bdone = true;
2854  }
2855  };
2856  }
2857  }
2858  }
2859  }
2860  }
2861 
2862  }
2863  }
2864  preBalance21(newmodified);
2865  u32vector().swap(modified);
2866  swap(modified,newmodified);
2867  modsize = modified.size();
2868  u32vector().swap(newmodified);
2869  }// end while
2870 
2871  }
2872  else{
2873  // Loop on ghost octants (influence over interior borders)
2874  obegin = ghosts.begin();
2875  oend = ghosts.end();
2876  idx = 0;
2877  for (it=obegin; it!=oend; it++){
2878  //if (!it->getNotBalance() && (it->info[11] || it->getMarker() != 0)){
2879  if (!it->getNotBalance() && (it->info[11])){
2880  targetmarker = min(MAX_LEVEL_2D, (it->getLevel()+it->getMarker()));
2881 
2882  //Balance through faces
2883  for (iface=0; iface<global2D.nfaces; iface++){
2884  if(it->getPbound(iface) == true){
2885  neigh.clear();
2886  findGhostNeighbours(idx, iface, neigh);
2887  sizeneigh = neigh.size();
2888  for(i=0; i<sizeneigh; i++){
2889  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2890  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2891  octants[neigh[i]].info[11] = true;
2892  modified.push_back(neigh[i]);
2893  Bdone = true;
2894  }
2895  }
2896  }
2897  }
2898 
2899  if (balance_codim>1){
2900  //Balance through nodes
2901  for (inode=0; inode<global2D.nnodes; inode++){
2902  if(it->getPbound(global2D.nodeface[inode][0]) == true || it->getPbound(global2D.nodeface[inode][1]) == true){
2903  neigh.clear();
2904  findGhostNodeNeighbours(idx, inode, neigh);
2905  sizeneigh = neigh.size();
2906  for(i=0; i<sizeneigh; i++){
2907  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2908  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2909  octants[neigh[i]].info[11] = true;
2910  modified.push_back(neigh[i]);
2911  Bdone = true;
2912  }
2913  }
2914  }
2915  }
2916  }
2917 
2918  }
2919  idx++;
2920  }
2921 
2922  // While loop for iterative balancing
2923  u32vector().swap(newmodified);
2924  modsize = modified.size();
2925  while(modsize!=0){
2926  ibegin = modified.begin();
2927  iend = modified.end();
2928  for (iit=ibegin; iit!=iend; iit++){
2929  idx = *iit;
2930  if (!octants[idx].getNotBalance()){
2931  targetmarker = min(MAX_LEVEL_2D, (octants[idx].getLevel()+octants[idx].getMarker()));
2932 
2933  //Balance through faces
2934  for (iface=0; iface<global2D.nfaces; iface++){
2935  if(!octants[idx].getPbound(iface)){
2936  findNeighbours(idx, iface, neigh, isghost);
2937  sizeneigh = neigh.size();
2938  for(i=0; i<sizeneigh; i++){
2939  if (!isghost[i]){
2940  {
2941  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1)){
2942  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-octants[idx].getLevel()-1);
2943  octants[idx].info[11] = true;
2944  newmodified.push_back(idx);
2945  Bdone = true;
2946  }
2947  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2948  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2949  octants[neigh[i]].info[11] = true;
2950  newmodified.push_back(neigh[i]);
2951  Bdone = true;
2952  }
2953  };
2954  }
2955  }
2956  }
2957  }
2958 
2959  if (balance_codim>1){
2960  //Balance through nodes
2961  for (inode=0; inode<global2D.nnodes; inode++){
2962  if(!octants[idx].getPbound(global2D.nodeface[inode][0]) || !octants[idx].getPbound(global2D.nodeface[inode][1])){
2963  findNodeNeighbours(idx, inode, neigh, isghost);
2964  sizeneigh = neigh.size();
2965  for(i=0; i<sizeneigh; i++){
2966  if (!isghost[i]){
2967  {
2968  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1)){
2969  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-octants[idx].getLevel()-1);
2970  octants[idx].info[11] = true;
2971  newmodified.push_back(idx);
2972  Bdone = true;
2973  }
2974  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
2975  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
2976  octants[neigh[i]].info[11] = true;
2977  newmodified.push_back(neigh[i]);
2978  Bdone = true;
2979  }
2980  };
2981  }
2982  }
2983  }
2984  }
2985  }
2986 
2987  }
2988  }
2989  preBalance21(newmodified);
2990  u32vector().swap(modified);
2991  swap(modified,newmodified);
2992  modsize = modified.size();
2993  u32vector().swap(newmodified);
2994  }// end while
2995  obegin = oend = octants.end();
2996  ibegin = iend = modified.end();
2997  }
2998  return Bdone;
2999  // Pay attention : info[11] may be true after local balance for some octants
3000  };
3001 
3002  // =================================================================================== //
3003 
3004  bool localBalanceAll(bool doInterior){ // 2:1 balancing on level a local tree already adapted (balance only the octants with info[14] = false) (refinement wins!)
3005  // Return true if balanced done with some markers modification
3006  // Seto doInterior = false if the interior octants are already balanced
3007  // Local variables
3008  uint32_t sizeneigh, modsize;
3009  u32vector neigh;
3010  u32vector modified, newmodified;
3011  uint32_t i, idx;
3012  uint8_t iface, inode;
3013  int8_t targetmarker;
3014  vector<bool> isghost;
3015  bool Bdone = false;
3016 
3017  OctantsType::iterator obegin, oend, it;
3018  u32vector::iterator ibegin, iend, iit;
3019 
3020  //If interior octants have to be balanced
3021  if(doInterior){
3022  // First loop on the octants
3023  obegin = octants.begin();
3024  oend = octants.end();
3025  idx = 0;
3026  for (it=obegin; it!=oend; it++){
3027  if ((!it->getNotBalance()) && ((it->info[11]) || (it->getMarker()!=0) || ((it->getIsNewC()) || (it->getIsNewR())))){
3028  targetmarker = min(MAX_LEVEL_2D, int(octants[idx].getLevel()) + int(octants[idx].getMarker()));
3029 
3030  //Balance through faces
3031  for (iface=0; iface<global2D.nfaces; iface++){
3032  if(!it->getBound(iface)){
3033  findNeighbours(idx, iface, neigh, isghost);
3034  sizeneigh = neigh.size();
3035  for(i=0; i<sizeneigh; i++){
3036  if (!isghost[i]){
3037  {
3038  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1) ){
3039  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-1-octants[idx].getLevel());
3040  octants[idx].info[11] = true;
3041  modified.push_back(idx);
3042  Bdone = true;
3043  }
3044  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3045  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3046  octants[neigh[i]].info[11] = true;
3047  modified.push_back(neigh[i]);
3048  Bdone = true;
3049  }
3050  };
3051  }
3052  else{
3053  {
3054  if((ghosts[neigh[i]].getLevel() + ghosts[neigh[i]].getMarker()) > (targetmarker + 1) ){
3055  octants[idx].setMarker(ghosts[neigh[i]].getLevel()+ghosts[neigh[i]].getMarker()-1-octants[idx].getLevel());
3056  octants[idx].info[11] = true;
3057  modified.push_back(idx);
3058  Bdone = true;
3059  }
3060  };
3061 
3062  }
3063  }
3064  }
3065  }
3066 
3067  if (balance_codim>1){
3068  //Balance through nodes
3069  for (inode=0; inode<global2D.nnodes; inode++){
3070  if(!it->getBound(global2D.nodeface[inode][0]) && !it->getBound(global2D.nodeface[inode][1])){
3071  findNodeNeighbours(idx, inode, neigh, isghost);
3072  sizeneigh = neigh.size();
3073  for(i=0; i<sizeneigh; i++){
3074  if (!isghost[i]){
3075  {
3076  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1) ){
3077  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-1-octants[idx].getLevel());
3078  octants[idx].info[11] = true;
3079  modified.push_back(idx);
3080  Bdone = true;
3081  }
3082  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3083  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3084  octants[neigh[i]].info[11] = true;
3085  modified.push_back(neigh[i]);
3086  Bdone = true;
3087  }
3088  };
3089  }
3090  else{
3091  if((ghosts[neigh[i]].getLevel() + ghosts[neigh[i]].getMarker()) > (targetmarker + 1) ){
3092  octants[idx].setMarker(ghosts[neigh[i]].getLevel()+ghosts[neigh[i]].getMarker()-1-octants[idx].getLevel());
3093  octants[idx].info[11] = true;
3094  modified.push_back(idx);
3095  Bdone = true;
3096  }
3097  }
3098  }
3099  }
3100  }
3101  }
3102 
3103  }
3104  idx++;
3105  }
3106  // Loop on ghost octants (influence over interior borders)
3107  obegin = ghosts.begin();
3108  oend = ghosts.end();
3109  idx = 0;
3110  for (it=obegin; it!=oend; it++){
3111  if (!it->getNotBalance() && (it->info[11] || (it->getIsNewC() || it->getIsNewR()))){
3112  targetmarker = min(MAX_LEVEL_2D, (it->getLevel()+it->getMarker()));
3113 
3114  //Balance through faces
3115  for (iface=0; iface<global2D.nfaces; iface++){
3116  if(it->getPbound(iface) == true){
3117  neigh.clear();
3118  findGhostNeighbours(idx, iface, neigh);
3119  sizeneigh = neigh.size();
3120  for(i=0; i<sizeneigh; i++){
3121  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3122  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3123  octants[neigh[i]].info[11] = true;
3124  modified.push_back(neigh[i]);
3125  Bdone = true;
3126  }
3127  }
3128  }
3129  }
3130 
3131  if (balance_codim>1){
3132  //Balance through nodes
3133  for (inode=0; inode<global2D.nnodes; inode++){
3134  if(it->getPbound(global2D.nodeface[inode][0]) == true || it->getPbound(global2D.nodeface[inode][1]) == true){
3135  neigh.clear();
3136  findGhostNodeNeighbours(idx, inode, neigh);
3137  sizeneigh = neigh.size();
3138  for(i=0; i<sizeneigh; i++){
3139  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3140  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3141  octants[neigh[i]].info[11] = true;
3142  modified.push_back(neigh[i]);
3143  Bdone = true;
3144  }
3145  }
3146  }
3147  }
3148  }
3149 
3150  }
3151  idx++;
3152  }
3153 
3154  // While loop for iterative balancing
3155  u32vector().swap(newmodified);
3156  modsize = modified.size();
3157  while(modsize!=0){
3158  ibegin = modified.begin();
3159  iend = modified.end();
3160  for (iit=ibegin; iit!=iend; iit++){
3161  idx = *iit;
3162  if (!octants[idx].getNotBalance()){
3163  targetmarker = min(MAX_LEVEL_2D, (octants[idx].getLevel()+octants[idx].getMarker()));
3164 
3165  //Balance through nodes
3166  for (iface=0; iface<global2D.nfaces; iface++){
3167  if(!octants[idx].getPbound(iface)){
3168  findNeighbours(idx, iface, neigh, isghost);
3169  sizeneigh = neigh.size();
3170  for(i=0; i<sizeneigh; i++){
3171  if (!isghost[i]){
3172  {
3173  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1)){
3174  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-octants[idx].getLevel()-1);
3175  octants[idx].info[11] = true;
3176  newmodified.push_back(idx);
3177  Bdone = true;
3178  }
3179  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3180  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3181  octants[neigh[i]].info[11] = true;
3182  newmodified.push_back(neigh[i]);
3183  Bdone = true;
3184  }
3185  };
3186  }
3187  }
3188  }
3189  }
3190 
3191  if (balance_codim>1){
3192  //Balance through nodes
3193  for (inode=0; inode<global2D.nnodes; inode++){
3194  if(!octants[idx].getPbound(global2D.nodeface[inode][0]) || !octants[idx].getPbound(global2D.nodeface[inode][1])){
3195  findNodeNeighbours(idx, inode, neigh, isghost);
3196  sizeneigh = neigh.size();
3197  for(i=0; i<sizeneigh; i++){
3198  if (!isghost[i]){
3199  {
3200  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1)){
3201  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-octants[idx].getLevel()-1);
3202  octants[idx].info[11] = true;
3203  newmodified.push_back(idx);
3204  Bdone = true;
3205  }
3206  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3207  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3208  octants[neigh[i]].info[11] = true;
3209  newmodified.push_back(neigh[i]);
3210  Bdone = true;
3211  }
3212  };
3213  }
3214  }
3215  }
3216  }
3217  }
3218 
3219  }
3220  }
3221  preBalance21(newmodified);
3222  u32vector().swap(modified);
3223  swap(modified,newmodified);
3224  modsize = modified.size();
3225  u32vector().swap(newmodified);
3226  }// end while
3227 
3228  }
3229  else{
3230 
3231  // Loop on ghost octants (influence over interior borders)
3232  obegin = ghosts.begin();
3233  oend = ghosts.end();
3234  idx = 0;
3235  for (it=obegin; it!=oend; it++){
3236  if (!it->getNotBalance() && (it->info[11] || (it->getIsNewC() || it->getIsNewR()))){
3237  targetmarker = min(MAX_LEVEL_2D, (it->getLevel()+it->getMarker()));
3238 
3239  //Balance through faces
3240  for (iface=0; iface<global2D.nfaces; iface++){
3241  if(it->getPbound(iface) == true){
3242  neigh.clear();
3243  findGhostNeighbours(idx, iface, neigh);
3244  sizeneigh = neigh.size();
3245  for(i=0; i<sizeneigh; i++){
3246  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3247  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3248  octants[neigh[i]].info[11] = true;
3249  modified.push_back(neigh[i]);
3250  Bdone = true;
3251  }
3252  }
3253  }
3254  }
3255 
3256  if (balance_codim>1){
3257  //Balance through nodes
3258  for (inode=0; inode<global2D.nnodes; inode++){
3259  if(it->getPbound(global2D.nodeface[inode][0]) == true || it->getPbound(global2D.nodeface[inode][0]) == true){
3260  neigh.clear();
3261  findGhostNodeNeighbours(idx, inode, neigh);
3262  sizeneigh = neigh.size();
3263  for(i=0; i<sizeneigh; i++){
3264  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3265  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3266  octants[neigh[i]].info[11] = true;
3267  modified.push_back(neigh[i]);
3268  Bdone = true;
3269  }
3270  }
3271  }
3272  }
3273  }
3274 
3275  }
3276  idx++;
3277  }
3278 
3279  // While loop for iterative balancing
3280  u32vector().swap(newmodified);
3281  modsize = modified.size();
3282  while(modsize!=0){
3283  ibegin = modified.begin();
3284  iend = modified.end();
3285  for (iit=ibegin; iit!=iend; iit++){
3286  idx = *iit;
3287  if (!octants[idx].getNotBalance()){
3288  targetmarker = min(MAX_LEVEL_2D, (octants[idx].getLevel()+octants[idx].getMarker()));
3289 
3290  //Balance through faces
3291  for (iface=0; iface<global2D.nfaces; iface++){
3292  if(!octants[idx].getPbound(iface)){
3293  findNeighbours(idx, iface, neigh, isghost);
3294  sizeneigh = neigh.size();
3295  for(i=0; i<sizeneigh; i++){
3296  if (!isghost[i]){
3297  {
3298  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1)){
3299  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-octants[idx].getLevel()-1);
3300  octants[idx].info[11] = true;
3301  newmodified.push_back(idx);
3302  Bdone = true;
3303  }
3304  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3305  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3306  octants[neigh[i]].info[11] = true;
3307  newmodified.push_back(neigh[i]);
3308  Bdone = true;
3309  }
3310  };
3311  }
3312  }
3313  }
3314  }
3315 
3316  if (balance_codim>1){
3317  //Balance through nodes
3318  for (inode=0; inode<global2D.nnodes; inode++){
3319  if(!octants[idx].getPbound(global2D.nodeface[inode][0]) || !octants[idx].getPbound(global2D.nodeface[inode][1])){
3320  findNodeNeighbours(idx, inode, neigh, isghost);
3321  sizeneigh = neigh.size();
3322  for(i=0; i<sizeneigh; i++){
3323  if (!isghost[i]){
3324  {
3325  if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) > (targetmarker + 1)){
3326  octants[idx].setMarker(octants[neigh[i]].getLevel()+octants[neigh[i]].getMarker()-octants[idx].getLevel()-1);
3327  octants[idx].info[11] = true;
3328  newmodified.push_back(idx);
3329  Bdone = true;
3330  }
3331  else if((octants[neigh[i]].getLevel() + octants[neigh[i]].getMarker()) < (targetmarker - 1)){
3332  octants[neigh[i]].setMarker(targetmarker-octants[neigh[i]].getLevel()-1);
3333  octants[neigh[i]].info[11] = true;
3334  newmodified.push_back(neigh[i]);
3335  Bdone = true;
3336  }
3337  };
3338  }
3339  }
3340  }
3341  }
3342  }
3343 
3344  }
3345  }
3346  preBalance21(newmodified);
3347  u32vector().swap(modified);
3348  swap(modified,newmodified);
3349  modsize = modified.size();
3350  u32vector().swap(newmodified);
3351  }// end while
3352  obegin = oend = octants.end();
3353  ibegin = iend = modified.end();
3354  }
3355  return Bdone;
3356  // Pay attention : info[11] may be true after local balance for some octants
3357  };
3358 
3359  // =================================================================================== //
3360 
3361  void findNodeNeighbours(uint32_t idx, // Finds neighbours of idx-th octant through inode in vector octants.
3362  uint8_t inode, // Returns a vector (empty if inode is a bound node) with the index of neighbours
3363  u32vector & neighbours, // in their structure (octants or ghosts) and sets isghost[i] = true if the
3364  vector<bool> & isghost){ // i-th neighbour is ghost in the local tree
3365 
3366  uint64_t Morton, Mortontry;
3367  uint32_t noctants = getNumOctants();
3368  uint32_t idxtry;
3369  Class_Octant<2>* oct = &octants[idx];
3370  uint32_t size = oct->getSize();
3371  uint8_t iface1, iface2;
3372  int32_t Dhx, Dhy;
3373  int32_t Dhxref, Dhyref;
3374 
3375  //Alternative to switch case
3376  int8_t Cx[4] = {-1,1,-1,1};
3377  int8_t Cy[4] = {-1,-1,1,1};
3378  int8_t cx = Cx[inode];
3379  int8_t cy = Cy[inode];
3380 
3381  isghost.clear();
3382  neighbours.clear();
3383 
3384  // Default if inode is nnodes<inode<0
3385  if (inode < 0 || inode > global2D.nnodes){
3386  return;
3387  }
3388 
3389  // Check if octants node is a boundary
3390  iface1 = global2D.nodeface[inode][0];
3391  iface2 = global2D.nodeface[inode][1];
3392 
3393  // Check if octants node is a boundary
3394  if (oct->info[iface1] == false && oct->info[iface2] == false){
3395 
3396  //Build Morton number of virtual neigh of same size
3397  Class_Octant<2> samesizeoct(oct->level, int32_t(oct->x)+int32_t(cx)*int32_t(size), int32_t(oct->y)+int32_t(cy)*int32_t(size));
3398  Morton = samesizeoct.computeMorton();
3399 
3400  //SEARCH IN GHOSTS
3401 
3402  if (ghosts.size()>0){
3403  // Search in ghosts
3404 
3405  uint32_t idxghost = uint32_t(size_ghosts/2);
3406  Class_Octant<2>* octghost = &ghosts[idxghost];
3407 
3408  // Search morton in octants
3409  // If a even face morton is lower than morton of oct, if odd higher
3410  // ---> can i search only before or after idx in octants
3411  int32_t jump;
3412  if (inode==3 || inode ==0){
3413  jump = (octghost->computeMorton() > Morton) ? int32_t(idxghost/2+1) : int32_t((size_ghosts -idxghost)/2+1);
3414  idxtry = uint32_t(idxghost +((octghost->computeMorton()<Morton)-(octghost->computeMorton()>Morton))*jump);
3415  if (idxtry > size_ghosts-1)
3416  idxtry = size_ghosts-1;
3417  }
3418  else{
3419  jump = idxghost;
3420  idxtry = uint32_t(jump);
3421  }
3422  while(abs(jump) > 0){
3423  Mortontry = ghosts[idxtry].computeMorton();
3424  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
3425  idxtry += jump;
3426  if (idxtry > ghosts.size()-1){
3427  if (jump > 0){
3428  idxtry = ghosts.size() - 1;
3429  jump = 0;
3430  }
3431  else if (jump < 0){
3432  idxtry = 0;
3433  jump = 0;
3434  }
3435  }
3436  }
3437  if(ghosts[idxtry].computeMorton() == Morton && ghosts[idxtry].level == oct->level){
3438  //Found neighbour of same size
3439  isghost.push_back(true);
3440  neighbours.push_back(idxtry);
3441  return;
3442  }
3443  else{
3444  // Step until the mortontry lower than morton (one idx of distance)
3445  {
3446  while(ghosts[idxtry].computeMorton() < Morton){
3447  idxtry++;
3448  if(idxtry > ghosts.size()-1){
3449  idxtry = ghosts.size()-1;
3450  break;
3451  }
3452  }
3453  while(ghosts[idxtry].computeMorton() > Morton){
3454  idxtry--;
3455  if(idxtry > ghosts.size()-1){
3456  idxtry = 0;
3457  break;
3458  }
3459  }
3460  }
3461  if(idxtry < size_ghosts){
3462  if(ghosts[idxtry].computeMorton() == Morton && ghosts[idxtry].level == oct->level){
3463  //Found neighbour of same size
3464  isghost.push_back(true);
3465  neighbours.push_back(idxtry);
3466  return;
3467  }
3468  // Compute Last discendent of virtual octant of same size
3469  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
3470  uint64_t Mortonlast = last_desc.computeMorton();
3471  Mortontry = ghosts[idxtry].computeMorton();
3472  while(Mortontry < Mortonlast && idxtry < size_ghosts){
3473  Dhx = (-int32_t(oct->x) + int32_t(ghosts[idxtry].x));
3474  Dhy = (-int32_t(oct->y) + int32_t(ghosts[idxtry].y));
3475  Dhxref = int32_t(cx<0)*(-int32_t(ghosts[idxtry].getSize())) + int32_t(cx>0)*size;
3476  Dhyref = int32_t(cy<0)*(-int32_t(ghosts[idxtry].getSize())) + int32_t(cy>0)*size;
3477  if ((Dhx == Dhxref) && (Dhy == Dhyref)){
3478  neighbours.push_back(idxtry);
3479  isghost.push_back(true);
3480  return;
3481  }
3482  idxtry++;
3483  if(idxtry>size_ghosts-1){
3484  break;
3485  }
3486  Mortontry = ghosts[idxtry].computeMorton();
3487  }
3488  }
3489  }
3490  }
3491 
3492  // Search in octants
3493 
3494  // Search morton in octants
3495  // If a even face morton is lower than morton of oct, if odd higher
3496  // ---> can i search only before or after idx in octants
3497  int32_t jump;
3498  if (inode==0 || inode==3){
3499  jump = (oct->computeMorton() > Morton) ? int32_t(idx/2+1) : int32_t((noctants -idx)/2+1);
3500  idxtry = uint32_t(idx +((oct->computeMorton()<Morton)-(oct->computeMorton()>Morton))*jump);
3501  if (idxtry > noctants-1)
3502  idxtry = noctants-1;
3503  }
3504  else{
3505  jump = noctants/2;
3506  idxtry = jump;
3507  }
3508  while(abs(jump) > 0){
3509  Mortontry = octants[idxtry].computeMorton();
3510  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
3511  idxtry += jump;
3512  if (idxtry > octants.size()-1){
3513  if (jump > 0){
3514  idxtry = octants.size() - 1;
3515  jump = 0;
3516  }
3517  else if (jump < 0){
3518  idxtry = 0;
3519  jump = 0;
3520  }
3521  }
3522  }
3523  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
3524  //Found neighbour of same size
3525  isghost.push_back(false);
3526  neighbours.push_back(idxtry);
3527  return;
3528  }
3529  else{
3530  // Step until the mortontry lower than morton (one idx of distance)
3531  {
3532  while(octants[idxtry].computeMorton() < Morton){
3533  idxtry++;
3534  if(idxtry > noctants-1){
3535  idxtry = noctants-1;
3536  break;
3537  }
3538  }
3539  while(octants[idxtry].computeMorton() > Morton){
3540  idxtry--;
3541  if(idxtry > noctants-1){
3542  idxtry = 0;
3543  break;
3544  }
3545  }
3546  }
3547  if (idxtry < noctants){
3548  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
3549  //Found neighbour of same size
3550  isghost.push_back(false);
3551  neighbours.push_back(idxtry);
3552  return;
3553  }
3554  // Compute Last discendent of virtual octant of same size
3555  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
3556  uint64_t Mortonlast = last_desc.computeMorton();
3557  Mortontry = octants[idxtry].computeMorton();
3558  while(Mortontry < Mortonlast && idxtry <= noctants-1){
3559  Dhx = (-int32_t(oct->x) + int32_t(octants[idxtry].x));
3560  Dhy = (-int32_t(oct->y) + int32_t(octants[idxtry].y));
3561  Dhxref = int32_t(cx<0)*(-int32_t(octants[idxtry].getSize())) + int32_t(cx>0)*size;
3562  Dhyref = int32_t(cy<0)*(-int32_t(octants[idxtry].getSize())) + int32_t(cy>0)*size;
3563  if ((Dhx == Dhxref) && (Dhy == Dhyref)){
3564  neighbours.push_back(idxtry);
3565  isghost.push_back(false);
3566  return;
3567  }
3568  idxtry++;
3569  if(idxtry>noctants-1){
3570  break;
3571  }
3572  Mortontry = octants[idxtry].computeMorton();
3573  }
3574  }
3575  }
3576  return;
3577  }
3578  else{
3579  // Boundary Node
3580  return;
3581  }
3582 
3583  };
3584 
3585  // =================================================================================== //
3586 
3587  void findNodeNeighbours(Class_Octant<2>* oct, // Finds neighbours of idx-th octant through inode in vector octants.
3588  uint8_t inode, // Returns a vector (empty if inode is a bound node) with the index of neighbours
3589  u32vector & neighbours, // in their structure (octants or ghosts) and sets isghost[i] = true if the
3590  vector<bool> & isghost){ // i-th neighbour is ghost in the local tree
3591 
3592  uint64_t Morton, Mortontry;
3593  uint32_t noctants = getNumOctants();
3594  uint32_t idxtry;
3595  uint32_t size = oct->getSize();
3596  uint8_t iface1, iface2;
3597  int32_t Dhx, Dhy;
3598  int32_t Dhxref, Dhyref;
3599 
3600  //Alternative to switch case
3601  int8_t Cx[4] = {-1,1,-1,1};
3602  int8_t Cy[4] = {-1,-1,1,1};
3603  int8_t cx = Cx[inode];
3604  int8_t cy = Cy[inode];
3605 
3606  isghost.clear();
3607  neighbours.clear();
3608 
3609  // Default if inode is nnodes<inode<0
3610  if (inode < 0 || inode > global2D.nnodes){
3611  return;
3612  }
3613 
3614  // Check if octants node is a boundary
3615  iface1 = global2D.nodeface[inode][0];
3616  iface2 = global2D.nodeface[inode][1];
3617 
3618  // Check if octants node is a boundary
3619  if (oct->info[iface1] == false && oct->info[iface2] == false){
3620 
3621  //Build Morton number of virtual neigh of same size
3622  Class_Octant<2> samesizeoct(oct->level, int32_t(oct->x)+int32_t(cx)*int32_t(size), int32_t(oct->y)+int32_t(cy)*int32_t(size));
3623  Morton = samesizeoct.computeMorton();
3624 
3625  //SEARCH IN GHOSTS
3626 
3627  if (ghosts.size()>0){
3628  // Search in ghosts
3629 
3630  uint32_t idxghost = uint32_t(size_ghosts/2);
3631  Class_Octant<2>* octghost = &ghosts[idxghost];
3632 
3633  // Search morton in octants
3634  // If a even face morton is lower than morton of oct, if odd higher
3635  // ---> can i search only before or after idx in octants
3636  int32_t jump = (octghost->computeMorton() > Morton) ? int32_t(idxghost/2+1) : int32_t((size_ghosts -idxghost)/2+1);
3637  idxtry = uint32_t(idxghost +((octghost->computeMorton()<Morton)-(octghost->computeMorton()>Morton))*jump);
3638  if (idxtry > size_ghosts-1)
3639  idxtry = size_ghosts-1;
3640  while(abs(jump) > 0){
3641  Mortontry = ghosts[idxtry].computeMorton();
3642  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
3643  idxtry += jump;
3644  if (idxtry > ghosts.size()-1){
3645  if (jump > 0){
3646  idxtry = ghosts.size() - 1;
3647  jump = 0;
3648  }
3649  else if (jump < 0){
3650  idxtry = 0;
3651  jump = 0;
3652  }
3653  }
3654  }
3655  if(ghosts[idxtry].computeMorton() == Morton && ghosts[idxtry].level == oct->level){
3656  //Found neighbour of same size
3657  isghost.push_back(true);
3658  neighbours.push_back(idxtry);
3659  return;
3660  }
3661  else{
3662  // Step until the mortontry lower than morton (one idx of distance)
3663  {
3664  while(ghosts[idxtry].computeMorton() < Morton){
3665  idxtry++;
3666  if(idxtry > ghosts.size()-1){
3667  idxtry = ghosts.size()-1;
3668  break;
3669  }
3670  }
3671  while(ghosts[idxtry].computeMorton() > Morton){
3672  idxtry--;
3673  if(idxtry > ghosts.size()-1){
3674  idxtry = 0;
3675  break;
3676  }
3677  }
3678  }
3679  if(idxtry < size_ghosts){
3680  if(ghosts[idxtry].computeMorton() == Morton && ghosts[idxtry].level == oct->level){
3681  //Found neighbour of same size
3682  isghost.push_back(true);
3683  neighbours.push_back(idxtry);
3684  return;
3685  }
3686  // Compute Last discendent of virtual octant of same size
3687  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
3688  uint64_t Mortonlast = last_desc.computeMorton();
3689  Mortontry = ghosts[idxtry].computeMorton();
3690  while(Mortontry < Mortonlast && idxtry < size_ghosts){
3691  Dhx = (-int32_t(oct->x) + int32_t(ghosts[idxtry].x));
3692  Dhy = (-int32_t(oct->y) + int32_t(ghosts[idxtry].y));
3693  Dhxref = int32_t(cx<0)*(-int32_t(ghosts[idxtry].getSize())) + int32_t(cx>0)*size;
3694  Dhyref = int32_t(cy<0)*(-int32_t(ghosts[idxtry].getSize())) + int32_t(cy>0)*size;
3695  if ((Dhx == Dhxref) && (Dhy == Dhyref)){
3696  neighbours.push_back(idxtry);
3697  isghost.push_back(true);
3698  return;
3699  }
3700  idxtry++;
3701  if(idxtry>size_ghosts-1){
3702  break;
3703  }
3704  Mortontry = ghosts[idxtry].computeMorton();
3705  }
3706  }
3707  }
3708  }
3709 
3710  // Search in octants
3711 
3712  //Build Morton number of virtual neigh of same size
3713  // Search morton in octants
3714  // If a even face morton is lower than morton of oct, if odd higher
3715  // ---> can i search only before or after idx in octants
3716  int32_t jump = int32_t((noctants)/2+1);
3717  idxtry = uint32_t(jump);
3718  if (idxtry > noctants-1)
3719  idxtry = noctants-1;
3720  while(abs(jump) > 0){
3721  Mortontry = octants[idxtry].computeMorton();
3722  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
3723  idxtry += jump;
3724  if (idxtry > octants.size()-1){
3725  if (jump > 0){
3726  idxtry = octants.size() - 1;
3727  jump = 0;
3728  }
3729  else if (jump < 0){
3730  idxtry = 0;
3731  jump = 0;
3732  }
3733  }
3734  }
3735  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
3736  //Found neighbour of same size
3737  isghost.push_back(false);
3738  neighbours.push_back(idxtry);
3739  return;
3740  }
3741  else{
3742  // Step until the mortontry lower than morton (one idx of distance)
3743  {
3744  while(octants[idxtry].computeMorton() < Morton){
3745  idxtry++;
3746  if(idxtry > noctants-1){
3747  idxtry = noctants-1;
3748  break;
3749  }
3750  }
3751  while(octants[idxtry].computeMorton() > Morton){
3752  idxtry--;
3753  if(idxtry > noctants-1){
3754  idxtry = 0;
3755  break;
3756  }
3757  }
3758  }
3759  if (idxtry < noctants){
3760  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
3761  //Found neighbour of same size
3762  isghost.push_back(false);
3763  neighbours.push_back(idxtry);
3764  return;
3765  }
3766  // Compute Last discendent of virtual octant of same size
3767  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
3768  uint64_t Mortonlast = last_desc.computeMorton();
3769  Mortontry = octants[idxtry].computeMorton();
3770  while(Mortontry < Mortonlast && idxtry <= noctants-1){
3771  Dhx = (-int32_t(oct->x) + int32_t(octants[idxtry].x));
3772  Dhy = (-int32_t(oct->y) + int32_t(octants[idxtry].y));
3773  Dhxref = int32_t(cx<0)*(-int32_t(octants[idxtry].getSize())) + int32_t(cx>0)*size;
3774  Dhyref = int32_t(cy<0)*(-int32_t(octants[idxtry].getSize())) + int32_t(cy>0)*size;
3775  if ((Dhx == Dhxref) && (Dhy == Dhyref)){
3776  neighbours.push_back(idxtry);
3777  isghost.push_back(false);
3778  return;
3779  }
3780  idxtry++;
3781  Mortontry = octants[idxtry].computeMorton();
3782  }
3783  }
3784  }
3785  return;
3786  }
3787  else{
3788  // Boundary Node
3789  return;
3790  }
3791 
3792  };
3793 
3794  // =================================================================================== //
3795 
3796  void findGhostNodeNeighbours(uint32_t const idx, // Finds neighbour of idx-th ghost octant through inode in vector octants.
3797  uint8_t inode, // Returns a vector (empty if inode is not a pbound node for ghost) with the index of neighbour
3798  u32vector & neighbours){ // in the structure octants
3799 
3800  uint64_t Morton, Mortontry;
3801  uint32_t noctants = getNumOctants();
3802  uint32_t idxtry;
3803  Class_Octant<2>* oct = &ghosts[idx];
3804  uint32_t size = oct->getSize();
3805  uint8_t iface1, iface2;
3806  int32_t Dhx, Dhy;
3807  int32_t Dhxref, Dhyref;
3808 
3809  //Alternative to switch case
3810  int8_t Cx[4] = {-1,1,-1,1};
3811  int8_t Cy[4] = {-1,-1,1,1};
3812  int8_t cx = Cx[inode];
3813  int8_t cy = Cy[inode];
3814 
3815  neighbours.clear();
3816 
3817  // Default if inode is nnodes<inode<0
3818  if (inode < 0 || inode > global2D.nnodes){
3819  return;
3820  }
3821 
3822  // Check if octants node is a boundary
3823  iface1 = global2D.nodeface[inode][0];
3824  iface2 = global2D.nodeface[inode][1];
3825 
3826 // // Check if octants node is a boundary
3827 // if (oct->info[iface1] == false && oct->info[iface2] == false){
3828  // Check if octants node is a pboundary node
3829  if (oct->info[iface1+global2D.nfaces] == true || oct->info[iface2+global2D.nfaces] == true){
3830 
3831  //Build Morton number of virtual neigh of same size
3832  Class_Octant<2> samesizeoct(oct->level, int32_t(oct->x)+int32_t(cx)*int32_t(size), int32_t(oct->y)+int32_t(cy)*int32_t(size));
3833  Morton = samesizeoct.computeMorton();
3834 
3835  // Search in octants
3836 
3837  // Search morton in octants
3838  // If a even face morton is lower than morton of oct, if odd higher
3839  // ---> can i search only before or after idx in octants
3840  int32_t jump = getNumOctants()/2;
3841  idxtry = uint32_t(getNumOctants()/2);
3842  while(abs(jump) > 0){
3843  Mortontry = octants[idxtry].computeMorton();
3844  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
3845  idxtry += jump;
3846  if (idxtry > octants.size()-1){
3847  if (jump > 0){
3848  idxtry = octants.size() - 1;
3849  jump = 0;
3850  }
3851  else if (jump < 0){
3852  idxtry = 0;
3853  jump = 0;
3854  }
3855  }
3856  }
3857  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
3858  //Found neighbour of same size
3859  neighbours.push_back(idxtry);
3860  return;
3861  }
3862  else{
3863  // Step until the mortontry lower than morton (one idx of distance)
3864  {
3865  while(octants[idxtry].computeMorton() < Morton){
3866  idxtry++;
3867  if(idxtry > noctants-1){
3868  idxtry = noctants-1;
3869  break;
3870  }
3871  }
3872  while(octants[idxtry].computeMorton() > Morton){
3873  idxtry--;
3874  if(idxtry > noctants-1){
3875  idxtry = 0;
3876  break;
3877  }
3878  }
3879  }
3880  if (idxtry < noctants){
3881  if(octants[idxtry].computeMorton() == Morton && octants[idxtry].level == oct->level){
3882  //Found neighbour of same size
3883  neighbours.push_back(idxtry);
3884  return;
3885  }
3886  // Compute Last discendent of virtual octant of same size
3887  Class_Octant<2> last_desc = samesizeoct.buildLastDesc();
3888  uint64_t Mortonlast = last_desc.computeMorton();
3889  Mortontry = octants[idxtry].computeMorton();
3890  while(Mortontry < Mortonlast && idxtry <= noctants-1){
3891  Dhx = (-int32_t(oct->x) + int32_t(octants[idxtry].x));
3892  Dhy = (-int32_t(oct->y) + int32_t(octants[idxtry].y));
3893  Dhxref = int32_t(cx<0)*(-int32_t(octants[idxtry].getSize())) + int32_t(cx>0)*size;
3894  Dhyref = int32_t(cy<0)*(-int32_t(octants[idxtry].getSize())) + int32_t(cy>0)*size;
3895  if ((Dhx == Dhxref) && (Dhy == Dhyref)){
3896  neighbours.push_back(idxtry);
3897  }
3898  idxtry++;
3899  if(idxtry>noctants-1){
3900  break;
3901  }
3902  Mortontry = octants[idxtry].computeMorton();
3903  }
3904  }
3905  }
3906  return;
3907  }
3908  else{
3909  // Boundary Node
3910  return;
3911  }
3912 
3913  };
3914 
3915  // =================================================================================== //
3916 
3917  void computeIntersections() {
3918 
3919  OctantsType::iterator it, obegin, oend;
3920  Class_Intersection<2> intersection;
3921  u32vector neighbours;
3922  vector<bool> isghost;
3923  uint32_t counter, idx;
3924  uint32_t i, nsize;
3925  uint8_t iface, iface2;
3926 
3927 
3928  intersections.clear();
3929  intersections.reserve(2*2*octants.size());
3930  counter = idx = 0;
3931 
3932  // Loop on ghosts
3933  obegin = ghosts.begin();
3934  oend = ghosts.end();
3935  for (it = obegin; it != oend; it++){
3936  for (iface = 0; iface < 2; iface++){
3937  iface2 = iface*2;
3938  findGhostNeighbours(idx, iface2, neighbours);
3939  nsize = neighbours.size();
3940  for (i = 0; i < nsize; i++){
3941  intersection.finer = getGhostLevel(idx) >= getLevel((int)neighbours[i]);
3942  intersection.owners[0] = neighbours[i];
3943  intersection.owners[1] = idx;
3944  intersection.iface = global2D.oppface[iface2] - (getGhostLevel(idx) >= getLevel((int)neighbours[i]));
3945  intersection.isnew = false;
3946  intersection.isghost = true;
3947  intersection.bound = false;
3948  intersection.pbound = true;
3949  intersections.push_back(intersection);
3950  counter++;
3951  }
3952  }
3953  idx++;
3954  }
3955  // Loop on octants
3956  idx=0;
3957  obegin = octants.begin();
3958  oend = octants.end();
3959  for (it = obegin; it != oend; it++){
3960  for (iface = 0; iface < 2; iface++){
3961  iface2 = iface*2;
3962  findNeighbours(idx, iface2, neighbours, isghost);
3963  nsize = neighbours.size();
3964  if (nsize) {
3965  for (i = 0; i < nsize; i++){
3966  if (isghost[i]){
3967  intersection.owners[0] = idx;
3968  intersection.owners[1] = neighbours[i];
3969  intersection.finer = (nsize>1);
3970  intersection.iface = iface2 + (nsize>1);
3971  intersection.isnew = false;
3972  intersection.isghost = true;
3973  intersection.bound = false;
3974  intersection.pbound = true;
3975  intersections.push_back(intersection);
3976  counter++;
3977  }
3978  else{
3979  intersection.owners[0] = idx;
3980  intersection.owners[1] = neighbours[i];
3981  intersection.finer = (nsize>1);
3982  intersection.iface = iface2 + (nsize>1);
3983  intersection.isnew = false;
3984  intersection.isghost = false;
3985  intersection.bound = false;
3986  intersection.pbound = false;
3987  intersections.push_back(intersection);
3988  counter++;
3989  }
3990  }
3991  }
3992  else{
3993  intersection.owners[0] = idx;
3994  intersection.owners[1] = idx;
3995  intersection.finer = 0;
3996  intersection.iface = iface2;
3997  intersection.isnew = false;
3998  intersection.isghost = false;
3999  intersection.bound = true;
4000  intersection.pbound = false;
4001  intersections.push_back(intersection);
4002  counter++;
4003  }
4004  if (it->info[iface2+1]){
4005  intersection.owners[0] = idx;
4006  intersection.owners[1] = idx;
4007  intersection.finer = 0;
4008  intersection.iface = iface2+1;
4009  intersection.isnew = false;
4010  intersection.isghost = false;
4011  intersection.bound = true;
4012  intersection.pbound = false;
4013  intersections.push_back(intersection);
4014  counter++;
4015  }
4016  }
4017  idx++;
4018  }
4019 #if defined(__INTEL_COMPILER) || defined(__ICC)
4020 #else
4021  intersections.shrink_to_fit();
4022 #endif
4023  }
4024 
4025  // =================================================================================== //
4026 
4027  uint32_t findMorton(uint64_t Morton){ // Find an input Morton in octants and return the local idx
4028  uint32_t nocts = octants.size();
4029  uint32_t idx = nocts/2;
4030  uint64_t Mortontry = octants[idx].computeMorton();
4031  int32_t jump = nocts/2;
4032  while(abs(jump)>0){
4033  if (Mortontry == Morton){
4034  return idx;
4035  }
4036  Mortontry = octants[idx].computeMorton();
4037  jump = ((Mortontry<Morton)-(Mortontry>Morton))*abs(jump)/2;
4038  idx += jump;
4039  if (idx > nocts){
4040  return nocts-1; // return nocts if not found the Morton
4041  }
4042  }
4043  if (Mortontry<Morton){
4044  for (uint32_t idx2=idx; idx2<nocts; idx2++){
4045  Mortontry = octants[idx2].computeMorton();
4046  if (Mortontry == Morton){
4047  return idx2;
4048  }
4049  }
4050  }
4051  else{
4052  for(uint32_t idx2=0; idx2<idx+1; idx2++){
4053  Mortontry = octants[idx2].computeMorton();
4054  if (Mortontry == Morton){
4055  return idx2;
4056  }
4057  }
4058  }
4059  return nocts-1;
4060  };
4061 
4062  // =================================================================================== //
4063 
4064  uint32_t findGhostMorton(uint64_t Morton){ // Find an input Morton in ghosts and return the local idx
4065  uint32_t nocts = ghosts.size();
4066  uint32_t idx = nocts/2;
4067  uint64_t Mortontry = ghosts[idx].computeMorton();
4068  int32_t jump = nocts/2;
4069  while(abs(jump)>0){
4070  if (Mortontry == Morton){
4071  return idx;
4072  }
4073  Mortontry = ghosts[idx].computeMorton();
4074  jump = (Mortontry<Morton)*jump/4;
4075  idx += jump;
4076  if (idx > nocts){
4077  return nocts; // return nocts if not found the Morton
4078  }
4079  }
4080  if (Mortontry<Morton){
4081  for (uint32_t idx2=idx; idx2<nocts; idx2++){
4082  Mortontry = ghosts[idx2].computeMorton();
4083  if (Mortontry == Morton){
4084  return idx2;
4085  }
4086  }
4087  }
4088  else{
4089  for(uint32_t idx2=0; idx2<idx; idx2++){
4090  Mortontry = ghosts[idx2].computeMorton();
4091  if (Mortontry == Morton){
4092  return idx2;
4093  }
4094  }
4095  }
4096  return nocts;
4097  };
4098 
4099  // =============================================================================== //
4100 
4103  void computeConnectivity() {
4104  map<uint64_t, vector<uint32_t> > mapnodes;
4105  map<uint64_t, vector<uint32_t> >::iterator iter, iterend;
4106  uint32_t i, k, counter;
4107  uint64_t morton;
4108  uint32_t noctants = getNumOctants();
4109  u32vector2D octnodes;
4110  uint8_t j;
4111 
4112  clearConnectivity();
4113 
4114  octnodes.reserve(global2D.nnodes);
4115  if (nodes.size() == 0){
4116  connectivity.resize(noctants);
4117  for (i = 0; i < noctants; i++){
4118  octants[i].getNodes(octnodes);
4119  for (j = 0; j < global2D.nnodes; j++){
4120 // morton = mortonEncode_magicbits(octnodes[j][0], octnodes[j][1]);
4121  morton = keyXY(octnodes[j][0], octnodes[j][1]);
4122  if (mapnodes[morton].size()==0){
4123  mapnodes[morton].reserve(8);
4124  for (k = 0; k < 3; k++){
4125  mapnodes[morton].push_back(octnodes[j][k]);
4126  }
4127  }
4128  mapnodes[morton].push_back(i);
4129  }
4130  u32vector2D().swap(octnodes);
4131  }
4132  iter = mapnodes.begin();
4133  iterend = mapnodes.end();
4134  counter = 0;
4135  uint32_t numnodes = mapnodes.size();
4136  nodes.resize(numnodes);
4137  while (iter != iterend){
4138  vector<uint32_t> nodecasting(iter->second.begin(), iter->second.begin()+3);
4139  nodes[counter] = nodecasting;
4140 #if defined(__INTEL_COMPILER) || defined(__ICC)
4141 #else
4142  nodes[counter].shrink_to_fit();
4143 #endif
4144  for(vector<uint32_t>::iterator iter2 = iter->second.begin()+3; iter2 != iter->second.end(); iter2++){
4145  if (connectivity[int(*iter2)].size()==0){
4146  connectivity[int(*iter2)].reserve(4);
4147  }
4148  connectivity[int(*iter2)].push_back(counter);
4149  }
4150  mapnodes.erase(iter++);
4151  counter++;
4152  }
4153 #if defined(__INTEL_COMPILER) || defined(__ICC)
4154 #else
4155  nodes.shrink_to_fit();
4156 #endif
4157  //Slow. Memory saving.
4158  for (uint32_t ii=0; ii<noctants; ii++){
4159 #if defined(__INTEL_COMPILER) || defined(__ICC)
4160 #else
4161  connectivity[ii].shrink_to_fit();
4162 #endif
4163  }
4164 
4165 // //Reorder connectivity
4166 // for (uint32_t ii=0; ii<noctants; ii++){
4167 // sortNodes(connectivity[ii]);
4168 // }
4169 
4170 #if defined(__INTEL_COMPILER) || defined(__ICC)
4171 #else
4172  connectivity.shrink_to_fit();
4173 #endif
4174  }
4175  map<uint64_t, vector<uint32_t> >().swap(mapnodes);
4176  iter = mapnodes.end();
4177  }
4178 
4179  // =================================================================================== //
4180 
4183  void clearConnectivity() {
4184  u32vector2D().swap(nodes);
4185  u32vector2D().swap(connectivity);
4186  }
4187 
4188  // =================================================================================== //
4189 
4192  void updateConnectivity() {
4193  clearConnectivity();
4194  computeConnectivity();
4195  }
4196 
4197  // =================================================================================== //
4198 
4201  void computeghostsConnectivity() {
4202  map<uint64_t, vector<uint32_t> > mapnodes;
4203  map<uint64_t, vector<uint32_t> >::iterator iter, iterend;
4204  uint32_t i, k, counter;
4205  uint64_t morton;
4206  uint32_t noctants = size_ghosts;
4207  u32vector2D octnodes;
4208  uint8_t j;
4209 
4210  octnodes.reserve(global2D.nnodes);
4211 
4212  if (ghostsnodes.size() == 0){
4213  ghostsconnectivity.resize(noctants);
4214  for (i = 0; i < noctants; i++){
4215  ghosts[i].getNodes(octnodes);
4216  for (j = 0; j < global2D.nnodes; j++){
4217 // morton = mortonEncode_magicbits(octnodes[j][0], octnodes[j][1]);
4218  morton = keyXY(octnodes[j][0], octnodes[j][1]);
4219  if (mapnodes[morton].size()==0){
4220  for (k = 0; k < 3; k++){
4221  mapnodes[morton].push_back(octnodes[j][k]);
4222  }
4223  }
4224  mapnodes[morton].push_back(i);
4225  }
4226  u32vector2D().swap(octnodes);
4227  }
4228  iter = mapnodes.begin();
4229  iterend = mapnodes.end();
4230  uint32_t numnodes = mapnodes.size();
4231  ghostsnodes.resize(numnodes);
4232  counter = 0;
4233  while (iter != iterend){
4234  vector<uint32_t> nodecasting(iter->second.begin(), iter->second.begin()+3);
4235  ghostsnodes[counter] = nodecasting;
4236 #if defined(__INTEL_COMPILER) || defined(__ICC)
4237 #else
4238  ghostsnodes[counter].shrink_to_fit();
4239 #endif
4240  for(vector<uint32_t>::iterator iter2 = iter->second.begin()+3; iter2 != iter->second.end(); iter2++){
4241  if (ghostsconnectivity[int(*iter2)].size()==0){
4242  ghostsconnectivity[int(*iter2)].reserve(4);
4243  }
4244  ghostsconnectivity[int(*iter2)].push_back(counter);
4245  }
4246  mapnodes.erase(iter++);
4247  counter++;
4248  }
4249 #if defined(__INTEL_COMPILER) || defined(__ICC)
4250 #else
4251  ghostsnodes.shrink_to_fit();
4252 #endif
4253  //Slow. Memory saving.
4254  for (uint32_t ii=0; ii<noctants; ii++){
4255 #if defined(__INTEL_COMPILER) || defined(__ICC)
4256 #else
4257  ghostsconnectivity[ii].shrink_to_fit();
4258 #endif
4259  }
4260 
4261 // //Reorder connectivity
4262 // for (uint32_t ii=0; ii<noctants; ii++){
4263 // sortNodes(ghostsconnectivity[ii]);
4264 // }
4265 
4266 #if defined(__INTEL_COMPILER) || defined(__ICC)
4267 #else
4268  ghostsconnectivity.shrink_to_fit();
4269 #endif
4270  }
4271  iter = mapnodes.end();
4272  }
4273 
4274  // =================================================================================== //
4275 
4278  void clearghostsConnectivity() {
4279  u32vector2D().swap(ghostsnodes);
4280  u32vector2D().swap(ghostsconnectivity);
4281  }
4282 
4283  // =================================================================================== //
4284 
4287  void updateghostsConnectivity() {
4288  clearghostsConnectivity();
4289  computeghostsConnectivity();
4290  }
4291 
4292  // =============================================================================== //
4293 
4294 
4295 };//end Class_Local_Tree<2> specialization;
4296 
int8_t getMarker() const
Parallel Octree Manager Class.
Octant class definition - 2D specialization.
uint64_t computeMorton() const
uint32_t getSize() const
void setMarker(int8_t marker)
uint8_t nodeface[4][2]
Intersection class definition - 2D specialization.
Local octree portion for each process.