Hermes2D  2.0
traverse.cpp
1 // This file is part of Hermes2D.
2 //
3 // Hermes2D is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
15 
16 #include "global.h"
17 #include "mesh.h"
18 #include "transformable.h"
19 #include "traverse.h"
20 namespace Hermes
21 {
22  namespace Hermes2D
23  {
24  static const Rect H2D_UNITY = { 0, 0, ONE, ONE };
25  Traverse::Traverse(bool master) : master(master)
26  {
27  }
28 
29  static int get_split_and_sons(Element* e, Rect* cr, Rect* er, int4& sons)
30  {
31  uint64_t hmid = (er->l + er->r) >> 1;
32  uint64_t vmid = (er->t + er->b) >> 1;
33 
34  if(e->bsplit())
35  {
36  if(cr->r <= hmid && cr->t <= vmid)
37  return (sons[0] = sons[1] = sons[2] = sons[3] = 0), 0;
38  else if(cr->l >= hmid && cr->t <= vmid)
39  return (sons[0] = sons[1] = sons[2] = sons[3] = 1), 0;
40  else if(cr->l >= hmid && cr->b >= vmid)
41  return (sons[0] = sons[1] = sons[2] = sons[3] = 2), 0;
42  else if(cr->r <= hmid && cr->b >= vmid)
43  return (sons[0] = sons[1] = sons[2] = sons[3] = 3), 0;
44  else if(cr->r <= hmid)
45  return (sons[0] = sons[1] = 0, sons[2] = sons[3] = 3), 1;
46  else if(cr->l >= hmid)
47  return (sons[0] = sons[1] = 1, sons[2] = sons[3] = 2), 1;
48  else if(cr->t <= vmid)
49  return (sons[0] = sons[3] = 0, sons[1] = sons[2] = 1), 2;
50  else if(cr->b >= vmid)
51  return (sons[0] = sons[3] = 3, sons[1] = sons[2] = 2), 2;
52  else
53  return (sons[0] = 0, sons[1] = 1, sons[2] = 2, sons[3] = 3), 3;
54  }
55  else if(e->hsplit())
56  {
57  if(cr->t <= vmid)
58  return (sons[0] = sons[1] = sons[2] = sons[3] = 4), 0;
59  else if(cr->b >= vmid)
60  return (sons[0] = sons[1] = sons[2] = sons[3] = 5), 0;
61  else
62  return (sons[0] = sons[1] = 4, sons[2] = sons[3] = 5), 1;
63  }
64  else // e->vsplit()
65  {
66  if(cr->r <= hmid)
67  return (sons[0] = sons[1] = sons[2] = sons[3] = 6), 0;
68  else if(cr->l >= hmid)
69  return (sons[0] = sons[1] = sons[2] = sons[3] = 7), 0;
70  else
71  return (sons[0] = sons[3] = 6, sons[1] = sons[2] = 7), 2;
72  }
73  }
74 
75  static void move_to_son(Rect* rnew, Rect* rold, int son)
76  {
77  uint64_t hmid = (rold->l + rold->r) >> 1;
78  uint64_t vmid = (rold->t + rold->b) >> 1;
79  if(rnew != rold)
80  memcpy(rnew, rold, sizeof(Rect));
81 
82  switch (son)
83  {
84  case 0: rnew->r = hmid; rnew->t = vmid; break;
85  case 1: rnew->l = hmid; rnew->t = vmid; break;
86  case 2: rnew->l = hmid; rnew->b = vmid; break;
87  case 3: rnew->r = hmid; rnew->b = vmid; break;
88  case 4: rnew->t = vmid; break;
89  case 5: rnew->b = vmid; break;
90  case 6: rnew->r = hmid; break;
91  case 7: rnew->l = hmid; break;
92  }
93  }
94 
95  void Traverse::init_transforms(Traverse::State* s, int i)
96  {
97  Rect r;
98  memcpy(&r, s->er + i, sizeof(Rect));
99 
100  while (s->cr.l > r.l || s->cr.r < r.r || s->cr.b > r.b || s->cr.t < r.t)
101  {
102  uint64_t hmid = (r.l + r.r) >> 1;
103  uint64_t vmid = (r.t + r.b) >> 1;
104  int son;
105 
106  if(s->cr.r <= hmid && s->cr.t <= vmid) son = 0;
107  else if(s->cr.l >= hmid && s->cr.t <= vmid) son = 1;
108  else if(s->cr.l >= hmid && s->cr.b >= vmid) son = 2;
109  else if(s->cr.r <= hmid && s->cr.b >= vmid) son = 3;
110  else if(s->cr.r <= hmid) son = 6;
111  else if(s->cr.l >= hmid) son = 7;
112  else if(s->cr.t <= vmid) son = 4;
113  else if(s->cr.b >= vmid) son = 5;
114  else assert(0);
115 
116  s->push_transform(son, i, s->rep->is_triangle());
117  move_to_son(&r, &r, son);
118  }
119  }
120 
121  Traverse::State::State()
122  {
123  memset(this, 0, sizeof(Traverse::State));
124  for(int i = 0; i < 4; i++)
125  this->bnd[i] = true;
126  cr = H2D_UNITY;
127  for (int i = 0; i < num; i++)
128  er[i] = H2D_UNITY;
129  isurf = -1;
130  }
131 
132  void Traverse::State::operator=(const State * other)
133  {
134  // Delete part.
135  if(e != NULL)
136  delete [] e;
137  if(sub_idx != NULL)
138  delete [] sub_idx;
139 
140  this->num = other->num;
141 
142  this->e = new Element*[num];
143  this->sub_idx = new uint64_t[num];
144  memcpy(this->e, other->e, num * sizeof(Element*));
145  memcpy(this->sub_idx, other->sub_idx, num * sizeof(uint64_t));
146  memcpy(this->bnd, other->bnd, 4 * sizeof(bool));
147 
148  this->rep = other->rep;
149  this->visited = other->visited;
150  this->isurf = other->isurf;
151  this->isBnd = other->isBnd;
152  }
153 
154  Traverse::State::~State()
155  {
156  if(e != NULL)
157  delete [] e;
158  if(sub_idx != NULL)
159  delete [] sub_idx;
160  }
161 
162  void Traverse::State::push_transform(int son, int i, bool is_triangle)
163  {
164  this->sub_idx[i] = (sub_idx[i] << 3) + son + 1;
165 
166  if(is_triangle)
167  {
168  if(son < 3)
169  {
170  switch (son)
171  {
172  case 0: bnd[1] = false; break;
173  case 1: bnd[2] = false; break;
174  case 2: bnd[0] = false; break;
175  }
176  }
177  else
178  {
179  memset(bnd, 0, sizeof(bnd));
180  }
181  }
182  else
183  {
184  if(son != 0 && son != 1 && son != 4 && son != 6 && son != 7)
185  bnd[0] = false;
186  if(son != 1 && son != 2 && son != 7 && son != 4 && son != 5)
187  bnd[1] = false;
188  if(son != 2 && son != 3 && son != 5 && son != 6 && son != 7)
189  bnd[2] = false;
190  if(son != 3 && son != 0 && son != 6 && son != 4 && son != 5)
191  bnd[3] = false;
192  }
193  }
194 
195  uint64_t Traverse::State::get_transform(int i)
196  {
197  return this->sub_idx[i];
198  }
199 
200  Traverse::State* Traverse::push_state(int* top_by_ref)
201  {
202  int* top_f = (top_by_ref == NULL) ? &this->top : top_by_ref;
203 
204  if(*top_f >= size)
205  throw Hermes::Exceptions::Exception("Stack overflow. Increase stack size.");
206 
207  if(stack[*top_f].e == NULL)
208  {
209  stack[*top_f].e = new Element*[num];
210  stack[*top_f].er = new Rect[num];
211  stack[*top_f].sub_idx = new uint64_t[num];
212  }
213 
214  stack[*top_f].visited = false;
215  stack[*top_f].isurf = -1;
216  memset(stack[*top_f].sub_idx, 0, num * sizeof(uint64_t));
217  for(int i = 0; i < 4; i++)
218  stack[*top_f].bnd[i] = true;
219  stack[*top_f].num = this->num;
220 
221  return stack + (*top_f)++;
222  }
223 
224  void Traverse::set_boundary_info(State* s)
225  {
226  Element* e = NULL;
227  for (int i = 0; i < num; i++)
228  if((e = s->e[i]) != NULL) break;
229 
230  if(s->rep->is_triangle())
231  {
232  for (int i = 0; i < 3; i++)
233  (s->bnd[i] = (s->bnd[i] && e->en[i]->bnd));
234  s->isBnd = s->bnd[0] || s->bnd[1] || s->bnd[2] || e->vn[0]->bnd || e->vn[1]->bnd || e->vn[2]->bnd;
235  }
236  else
237  {
238  s->bnd[0] = s->bnd[0] && (s->cr.b == 0) && e->en[0]->bnd;
239  s->bnd[1] = s->bnd[1] && (s->cr.r == ONE) && e->en[1]->bnd;
240  s->bnd[2] = s->bnd[2] && (s->cr.t == ONE) && e->en[2]->bnd;
241  s->bnd[3] = s->bnd[3] && (s->cr.l == 0) && e->en[3]->bnd;
242  s->isBnd = s->bnd[0] || s->bnd[1] || s->bnd[2] || s->bnd[3] || e->vn[0]->bnd || e->vn[1]->bnd || e->vn[2]->bnd || e->vn[3]->bnd;
243  }
244  }
245 
246  int Traverse::get_num_states(Hermes::vector<const Mesh*> meshes)
247  {
248  // This will be returned.
249  int count = 0;
250 
251  this->num = meshes.size();
252  this->begin(num, &meshes.front());
253 
254  while (1)
255  {
256  int i, son;
257  // When the stack of states is not empty (i.e. not at the beginning) the function starts here.
258  // If the top state was visited already, we are returning through it:
259  // undo all its transformations, pop it and continue with a non-visited one
260  State* s;
261 
262  while (top > 0 && (s = stack + top-1)->visited)
263  (top)--;
264 
265  // The stack is empty, take next base element
266  // The process starts here (at the beginning the stack is always empty, i.e. top == 0)
267  if(top <= 0)
268  {
269  // Push the state of a new base element.
270  // This function only allocates memory for the new state,
271  // with as many Elements* as there are meshes in this stage.
272  // (Traverse knows what stage it is, because it is being initialized by calling trav.begin(..)).
273  s = push_state();
274  s->cr = H2D_UNITY;
275  while (1)
276  {
277  // No more base elements? we're finished.
278  // Id is set to zero at the beginning by the function trav.begin(..).
279  if(id >= meshes[0]->get_num_base_elements())
280  {
281  this->finish();
282  return count;
283  }
284 
285  int nused = 0;
286  // The variable num is the number of meshes in the stage
287  for (i = 0; i < num; i++)
288  {
289  // Retrieve the Element with this id on the i-th mesh.
290  s->e[i] = meshes[i]->get_element(id);
291  if(!s->e[i]->used)
292  {
293  s->e[i] = NULL;
294  continue;
295  }
296  else
297  s->rep = s->e[i];
298  s->er[i] = H2D_UNITY;
299  nused++;
300  }
301  // If there is any used element in this stage we continue with the calculation
302  // (break this cycle looking for such an element id).
303  if(nused)
304  break;
305  (id)++;
306  }
307 
308  (id)++;
309 
310  if(s->rep->is_triangle())
311  for (i = 0; i < 3; i++)
312  s->bnd[i] = true;
313  }
314 
315  // Entering a new state, perform transformations.
316  s->visited = true;
317  for (i = 0; i < num; i++)
318  {
319  // ..where the element is used ..
320  if(s->e[i] != NULL)
321  if(s->sub_idx[i] == 0 && s->e[i]->active)
322  if(!s->rep->is_triangle())
323  init_transforms(s, i);
324  }
325 
326  // Is this the leaf state?
327  bool leaf = true;
328  for (i = 0; i < num; i++)
329  {
330  if(s->e[i] != NULL)
331  if(!s->e[i]->active)
332  {
333  leaf = false;
334  break;
335  }
336  }
337 
338  // if yes, set boundary flags and return the state
339  if(leaf)
340  {
341  count++;
342  continue;
343  }
344 
345  // Triangle: push son states
346  if(s->rep->is_triangle())
347  {
348  // Triangle always has 4 sons.
349  for (son = 0; son <= 3; son++)
350  {
351  State* ns = push_state();
352  // For every mesh..
353  for (i = 0; i < num; i++)
354  {
355  // ..if the element is not used.
356  if(s->e[i] == NULL)
357  {
358  ns->e[i] = NULL;
359  }
360  else if(s->e[i]->active)
361  {
362  ns->rep = s->e[i];
363  ns->e[i] = s->e[i];
364  ns->sub_idx[i] = s->sub_idx[i];
365  ns->push_transform(son, i, true);
366  }
367  // ..we move to the son.
368  else
369  {
370  ns->e[i] = s->e[i]->sons[son];
371  // If the son's element is active.
372  if(ns->e[i]->active)
373  ns->sub_idx[i] = 0;
374  if(ns->e[i] != NULL)
375  ns->rep = ns->e[i];
376  }
377  }
378 
379  // Determine boundary flags and positions for the new state.
380  if(son < 3)
381  {
382  memcpy(ns->bnd, s->bnd, sizeof(ns->bnd));
383 
384  switch (son)
385  {
386  case 0: ns->bnd[1] = false; break;
387  case 1: ns->bnd[2] = false; break;
388  case 2: ns->bnd[0] = false; break;
389  }
390  }
391  else
392  {
393  memset(ns->bnd, 0, sizeof(ns->bnd));
394  }
395  }
396  }
397  // Quad: this is a little more complicated, same principle, though.
398  else
399  {
400  // Obtain split types and son numbers for the current rectangle on all elements.
401  int4* current_sons = new int4[num];
402  int split = 0;
403  for (i = 0; i < num; i++)
404  if(s->e[i] != NULL && !s->e[i]->active)
405  split |= get_split_and_sons(s->e[i], &s->cr, s->er + i, current_sons[i]);
406 
407  // Both splits: recur to four sons, similar to triangles.
408  if(split == 3)
409  {
410  for (son = 0; son <= 3; son++)
411  {
412  State* ns = push_state();
413  // Sets the son's "base" rectangle to the correct one.
414  move_to_son(&ns->cr, &s->cr, son);
415 
416  for (i = 0; i < num; i++)
417  {
418  if(s->e[i] == NULL)
419  {
420  ns->e[i] = NULL;
421  }
422  else
423  {
424  if(s->e[i]->active)
425  {
426  ns->e[i] = s->e[i];
427  ns->sub_idx[i] = s->sub_idx[i];
428  ns->push_transform(son, i);
429  }
430  else
431  {
432  ns->e[i] = s->e[i]->sons[current_sons[i][son] & 3];
433  // Sets the son's "current mesh" rectangle correctly.
434  move_to_son(ns->er + i, s->er + i, current_sons[i][son]);
435  if(ns->e[i]->active)
436  ns->sub_idx[i] = 0;
437  }
438  if(ns->e[i] != NULL)
439  ns->rep = ns->e[i];
440  }
441  }
442  }
443  }
444  // V or h split, recur to two sons.
445  else if(split > 0)
446  {
447  int son0 = 4, son1 = 5;
448  if(split == 2) { son0 = 6; son1 = 7; }
449 
450  for (son = son0; son <= son1; son++)
451  {
452  State* ns = push_state();
453  move_to_son(&ns->cr, &s->cr, son);
454 
455  int j = (son == 4 || son == 6) ? 0 : 2;
456  for (i = 0; i < num; i++)
457  {
458  if(s->e[i] == NULL)
459  {
460  ns->e[i] = NULL;
461  }
462  else
463  {
464  if(s->e[i]->active)
465  {
466  ns->e[i] = s->e[i];
467  ns->sub_idx[i] = s->sub_idx[i];
468  ns->push_transform(son, i);
469  }
470  else
471  {
472  ns->e[i] = s->e[i]->sons[current_sons[i][j] & 3];
473  move_to_son(ns->er + i, s->er + i, current_sons[i][j]);
474  if(ns->e[i]->active)
475  ns->sub_idx[i] = 0;
476  }
477  if(ns->e[i] != NULL)
478  ns->rep = ns->e[i];
479  }
480  }
481  }
482  }
483 
484  // No splits, recur to one son.
485  else
486  {
487  State* ns = push_state();
488  memcpy(&ns->cr, &s->cr, sizeof(Rect));
489 
490  for (i = 0; i < num; i++)
491  {
492  if(s->e[i] == NULL)
493  {
494  ns->e[i] = NULL;
495  }
496  else if(s->e[i]->active)
497  {
498  ns->e[i] = s->e[i];
499  memcpy(&ns->er[i], &ns->cr, sizeof(Rect));
500  }
501  else
502  {
503  ns->e[i] = s->e[i]->sons[current_sons[i][0] & 3];
504  move_to_son(ns->er + i, s->er + i, current_sons[i][0]);
505  if(ns->e[i]->active)
506  ns->sub_idx[i] = 0;
507  if(ns->e[i] != NULL)
508  ns->rep = ns->e[i];
509  }
510  }
511  }
512  delete [] current_sons;
513  }
514  }
515  this->finish();
516  }
517 
518  Traverse::State* Traverse::get_next_state(int* top_by_ref, int* id_by_ref)
519  {
520  // Serial / parallel code.
521  int* top_f = (top_by_ref == NULL) ? &this->top : top_by_ref;
522  int* id_f = (id_by_ref == NULL) ? &this->id : id_by_ref;
523 
524  while (1)
525  {
526  int i, son;
527  // When the stack of states is not empty (i.e. not at the beginning) the function starts here.
528  // If the top state was visited already, we are returning through it:
529  // undo all its transformations, pop it and continue with a non-visited one
530  State* s;
531 
532  while (*top_f > 0 && (s = stack + (*top_f)-1)->visited)
533  (*top_f)--;
534 
535  // The stack is empty, take next base element
536  // The process starts here (at the beginning the stack is always empty, i.e. top == 0)
537  if(*top_f <= 0)
538  {
539  // Push the state of a new base element.
540  // This function only allocates memory for the new state,
541  // with as many Elements* as there are meshes in this stage.
542  // (Traverse knows what stage it is, because it is being initialized by calling trav.begin(..)).
543  s = push_state(top_f);
544  s->cr = H2D_UNITY;
545  while (1)
546  {
547  // No more base elements? we're finished.
548  // Id is set to zero at the beginning by the function trav.begin(..).
549  if(*id_f >= meshes[0]->get_num_base_elements())
550  return NULL;
551  int nused = 0;
552  // The variable num is the number of meshes in the stage
553  for (i = 0; i < num; i++)
554  {
555  // Retrieve the Element with this id on the i-th mesh.
556  s->e[i] = meshes[i]->get_element(*id_f);
557  if(!s->e[i]->used)
558  {
559  s->e[i] = NULL;
560  continue;
561  }
562  else
563  s->rep = s->e[i];
564  s->er[i] = H2D_UNITY;
565  nused++;
566  }
567  // If there is any used element in this stage we continue with the calculation
568  // (break this cycle looking for such an element id).
569  if(nused)
570  break;
571  (*id_f)++;
572  }
573 
574  (*id_f)++;
575 
576  if(s->rep->is_triangle())
577  for (i = 0; i < 3; i++)
578  s->bnd[i] = true;
579  }
580 
581  // Entering a new state, perform transformations.
582  s->visited = true;
583  for (i = 0; i < num; i++)
584  {
585  // ..where the element is used ..
586  if(s->e[i] != NULL)
587  if(s->sub_idx[i] == 0 && s->e[i]->active)
588  if(!s->rep->is_triangle())
589  init_transforms(s, i);
590  }
591 
592  // Is this the leaf state?
593  bool leaf = true;
594  for (i = 0; i < num; i++)
595  {
596  if(s->e[i] != NULL)
597  if(!s->e[i]->active)
598  {
599  leaf = false;
600  break;
601  }
602  }
603 
604  // if yes, set boundary flags and return the state
605  if(leaf)
606  {
607  if(fn != NULL)
608  for (i = 0; i < num; i++)
609  if(s->e[i] != NULL)
610  {
611  fn[i]->set_active_element(s->e[i]);
612  fn[i]->set_transform(s->sub_idx[i]);
613  }
614  set_boundary_info(s);
615  return s;
616  }
617 
618  // Triangle: push son states
619  if(s->rep->is_triangle())
620  {
621  // Triangle always has 4 sons.
622  for (son = 0; son <= 3; son++)
623  {
624  State* ns = push_state(top_f);
625  // For every mesh..
626  for (i = 0; i < num; i++)
627  {
628  // ..if the element is not used.
629  if(s->e[i] == NULL)
630  {
631  ns->e[i] = NULL;
632  }
633  else if(s->e[i]->active)
634  {
635  ns->rep = s->e[i];
636  ns->e[i] = s->e[i];
637  ns->sub_idx[i] = s->sub_idx[i];
638  ns->push_transform(son, i, true);
639  }
640  // ..we move to the son.
641  else
642  {
643  ns->e[i] = s->e[i]->sons[son];
644  // If the son's element is active.
645  if(ns->e[i]->active)
646  ns->sub_idx[i] = 0;
647  if(ns->e[i] != NULL)
648  ns->rep = ns->e[i];
649  }
650  }
651 
652  // Determine boundary flags and positions for the new state.
653  if(son < 3)
654  {
655  memcpy(ns->bnd, s->bnd, sizeof(ns->bnd));
656 
657  switch (son)
658  {
659  case 0: ns->bnd[1] = false; break;
660  case 1: ns->bnd[2] = false; break;
661  case 2: ns->bnd[0] = false; break;
662  }
663  }
664  else
665  {
666  memset(ns->bnd, 0, sizeof(ns->bnd));
667  }
668  }
669  }
670  // Quad: this is a little more complicated, same principle, though.
671  else
672  {
673  // Obtain split types and son numbers for the current rectangle on all elements.
674  int split = 0;
675  int4* current_sons = new int4[num];
676  for (i = 0; i < num; i++)
677  if(s->e[i] != NULL && !s->e[i]->active)
678  split |= get_split_and_sons(s->e[i], &s->cr, s->er + i, current_sons[i]);
679 
680  // Both splits: recur to four sons, similar to triangles.
681  if(split == 3)
682  {
683  for (son = 0; son <= 3; son++)
684  {
685  State* ns = push_state(top_f);
686  // Sets the son's "base" rectangle to the correct one.
687  move_to_son(&ns->cr, &s->cr, son);
688 
689  for (i = 0; i < num; i++)
690  {
691  if(s->e[i] == NULL)
692  {
693  ns->e[i] = NULL;
694  }
695  else if(s->e[i]->active)
696  {
697  ns->e[i] = s->e[i];
698  ns->sub_idx[i] = s->sub_idx[i];
699  ns->push_transform(son, i);
700  }
701  else
702  {
703  ns->e[i] = s->e[i]->sons[current_sons[i][son] & 3];
704  // Sets the son's "current mesh" rectangle correctly.
705  move_to_son(ns->er + i, s->er + i, current_sons[i][son]);
706  if(ns->e[i]->active)
707  ns->sub_idx[i] = 0;
708  }
709  if(ns->e[i] != NULL)
710  ns->rep = ns->e[i];
711  }
712  }
713  }
714  // V or h split, recur to two sons.
715  else if(split > 0)
716  {
717  int son0 = 4, son1 = 5;
718  if(split == 2) { son0 = 6; son1 = 7; }
719 
720  for (son = son0; son <= son1; son++)
721  {
722  State* ns = push_state(top_f);
723  move_to_son(&ns->cr, &s->cr, son);
724 
725  int j = (son == 4 || son == 6) ? 0 : 2;
726  for (i = 0; i < num; i++)
727  {
728  if(s->e[i] == NULL)
729  {
730  ns->e[i] = NULL;
731  }
732  else
733  {
734  if(s->e[i]->active)
735  {
736  ns->e[i] = s->e[i];
737  ns->sub_idx[i] = s->sub_idx[i];
738  ns->push_transform(son, i);
739  }
740  else
741  {
742  ns->e[i] = s->e[i]->sons[current_sons[i][j] & 3];
743  move_to_son(ns->er + i, s->er + i, current_sons[i][j]);
744  if(ns->e[i]->active)
745  ns->sub_idx[i] = 0;
746  }
747  if(ns->e[i] != NULL)
748  ns->rep = ns->e[i];
749  }
750  }
751  }
752  }
753 
754  // No splits, recur to one son.
755  else
756  {
757  State* ns = push_state(top_f);
758  memcpy(&ns->cr, &s->cr, sizeof(Rect));
759 
760  for (i = 0; i < num; i++)
761  {
762  if(s->e[i] == NULL)
763  {
764  ns->e[i] = NULL;
765  }
766  else if(s->e[i]->active)
767  {
768  ns->e[i] = s->e[i];
769  memcpy(&ns->er[i], &ns->cr, sizeof(Rect));
770  }
771  else
772  {
773  ns->e[i] = s->e[i]->sons[current_sons[i][0] & 3];
774  move_to_son(ns->er + i, s->er + i, current_sons[i][0]);
775  if(ns->e[i]->active)
776  ns->sub_idx[i] = 0;
777  if(ns->e[i] != NULL)
778  ns->rep = ns->e[i];
779  }
780  }
781  }
782  delete [] current_sons;
783  }
784  }
785  }
786 
787  void Traverse::begin(int n, const Mesh** meshes, Transformable** fn)
788  {
789  //if(stack != NULL) finish();
790 
791  assert(n > 0);
792  num = n;
793 
794  this->meshes = meshes;
795  this->fn = fn;
796 
797  size = 256;
798  if(master)
799  {
800  stack = new State[size];
801  memset(stack, 0, size * sizeof(State));
802 
803  sons = new int4[num];
804  subs = new uint64_t[num];
805 
806  id = 0;
807  top = 0;
808 
809  // Test whether all master meshes have the same number of elements.
810  int base_elem_num = meshes[0]->get_num_base_elements();
811  for (int i = 1; i < n; i++)
812  if(base_elem_num != meshes[i]->get_num_base_elements())
813  throw Hermes::Exceptions::Exception("Meshes not compatible in Traverse::begin().");
814 
815  Element* e;
816  // Test whether areas of corresponding elements are the same.
817  double *areas = new double[base_elem_num];
818  memset(areas, 0, base_elem_num*sizeof(double));
819 
820  // Read base element areas from the first mesh,
821  // Also get minimum element area.
822  int counter = 0;
823  double min_elem_area = 1e30;
824  for_all_base_elements_incl_inactive(e, meshes[0])
825  {
826  if(!e->used)
827  areas[counter] = 0.0;
828  else
829  {
830  areas[counter] = e->get_area();
831  if(areas[counter] < min_elem_area)
832  min_elem_area = areas[counter];
833  }
834 
835  counter++;
836  }
837  // take one mesh at a time and compare element areas to the areas[] array
838  double tolerance = min_elem_area/100.;
839 
840  if(min_elem_area < 0)
841  throw Exceptions::ValueException("min_elem_area", 0.0, 1e-10);
842 
843  for (int i = 1; i < n; i++)
844  {
845  counter = 0;
846  for_all_base_elements_incl_inactive(e, meshes[i])
847  {
848  if(e->used)
849  if(fabs(areas[counter] - e->get_area()) > tolerance && areas[counter] > 1e-15)
850  {
851  this->info("counter = %d, area_1 = %g, area_2 = %g.\n", counter, areas[counter], e->get_area());
852  throw Hermes::Exceptions::Exception("Meshes not compatible in Traverse::begin().");
853  }
854  counter++;
855  }
856  }
857  delete [] areas;
858  }
859  }
860 
861  void Traverse::free_state(Traverse::State* state)
862  {
863  delete [] state->e;
864  delete [] state->er;
865  delete [] state->sub_idx;
866  memset(state, 0, sizeof(Traverse::State));
867  }
868 
869  void Traverse::finish()
870  {
871  if(master)
872  {
873  delete [] subs;
874  delete [] sons;
875 
876  if(stack == NULL) return;
877 
878  for (int i = 0; i < size; i++)
879  if(stack[i].e != NULL)
880  free_state(stack + i);
881 
882  delete [] stack;
883  stack = NULL;
884  }
885  }
886 
887  uint64_t Traverse::init_idx(Rect* cr, Rect* er)
888  {
889  Rect r;
890  memcpy(&r, er, sizeof(Rect));
891 
892  uint64_t idx = 0;
893  while (cr->l > r.l || cr->r < r.r || cr->b > r.b || cr->t < r.t)
894  {
895  uint64_t hmid = (r.l + r.r) >> 1;
896  uint64_t vmid = (r.t + r.b) >> 1;
897  int son = -1;
898 
899  if(cr->r <= hmid && cr->t <= vmid) { son = 0; r.r = hmid; r.t = vmid; }
900  else if(cr->l >= hmid && cr->t <= vmid) { son = 1; r.l = hmid; r.t = vmid; }
901  else if(cr->l >= hmid && cr->b >= vmid) { son = 2; r.l = hmid; r.b = vmid; }
902  else if(cr->r <= hmid && cr->b >= vmid) { son = 3; r.r = hmid; r.b = vmid; }
903  else if(cr->t <= vmid) { son = 4; r.t = vmid; }
904  else if(cr->b >= vmid) { son = 5; r.b = vmid; }
905  else if(cr->r <= hmid) { son = 6; r.r = hmid; }
906  else if(cr->l >= hmid) { son = 7; r.l = hmid; }
907  else assert(0);
908 
909  idx = (idx << 3) + son + 1;
910  }
911  return idx;
912  }
913 
914  void Traverse::union_recurrent(Rect* cr, Element** e, Rect* er, uint64_t* idx, Element* uni)
915  {
916  int i, j, son;
917 
918  // are we at the bottom?
919  bool leaf = true;
920  for (i = 0; i < num; i++)
921  if(!e[i]->active)
922  {
923  leaf = false;
924  break;
925  }
926 
927  // if yes, store the element transformation indices
928  if(leaf)
929  {
930  if(udsize <= uni->id)
931  {
932  if(!udsize) udsize = 1024;
933  while (udsize <= uni->id) udsize *= 2;
934  for (i = 0; i < num; i++)
935  unidata[i] = (UniData*) realloc(unidata[i], udsize * sizeof(UniData));
936  }
937  for (i = 0; i < num; i++)
938  {
939  unidata[i][uni->id].e = e[i];
940  unidata[i][uni->id].idx = idx[i];
941  }
942  return;
943  }
944 
945  // state arrays
946  Element** e_new = new Element*[num];
947  Rect* er_new = new Rect[num];
948  Rect cr_new;
949 
950  int4* sons = new int4[num];
951  uint64_t* idx_new = new uint64_t[num];
952  memcpy(idx_new, idx, num*sizeof(uint64_t));
953 
954  if(tri)
955  {
956  // visit all sons of the triangle
957  unimesh->refine_element_id(uni->id);
958  for (son = 0; son <= 3; son++)
959  {
960  for (i = 0; i < num; i++)
961  {
962  if(e[i]->active)
963  {
964  e_new[i] = e[i];
965  idx_new[i] = (idx[i] << 3) + son + 1;
966  } else
967  e_new[i] = e[i]->sons[son];
968  }
969  union_recurrent(NULL, e_new, NULL, idx_new, uni->sons[son]);
970  }
971  }
972  else
973  {
974  // obtain split types and son numbers for the current rectangle on all elements
975  int split = 0;
976  for (i = 0; i < num; i++)
977  if(!e[i]->active)
978  split |= get_split_and_sons(e[i], cr, er + i, sons[i]);
979 
980  // both splits: recur to four sons
981  if(split == 3)
982  {
983  unimesh->refine_element_id(uni->id, 0);
984 
985  for (son = 0; son <= 3; son++)
986  {
987  move_to_son(&cr_new, cr, son);
988  for (i = 0; i < num; i++)
989  {
990  if(e[i]->active)
991  {
992  e_new[i] = e[i];
993  idx_new[i] = (idx[i] << 3) + son + 1;
994  } else
995  {
996  e_new[i] = e[i]->sons[sons[i][son] & 3];
997  move_to_son(&(er_new[i]), er + i, sons[i][son]);
998  if(e_new[i]->active) idx_new[i] = init_idx(&cr_new, &(er_new[i]));
999  }
1000  }
1001  union_recurrent(&cr_new, e_new, er_new, idx_new, uni->sons[son]);
1002  }
1003  }
1004  // v or h split, recur to two sons
1005  else if(split > 0)
1006  {
1007  unimesh->refine_element_id(uni->id, split);
1008 
1009  int son0 = 4, son1 = 5;
1010  if(split == 2) { son0 = 6; son1 = 7; }
1011 
1012  for (son = son0; son <= son1; son++)
1013  {
1014  move_to_son(&cr_new, cr, son);
1015  j = (son == 4 || son == 6) ? 0 : 2;
1016  for (i = 0; i < num; i++)
1017  {
1018  if(e[i]->active)
1019  {
1020  e_new[i] = e[i];
1021  idx_new[i] = (idx[i] << 3) + son + 1;
1022  } else
1023  {
1024  e_new[i] = e[i]->sons[sons[i][j] & 3];
1025  move_to_son(&(er_new[i]), er + i, sons[i][j]);
1026  if(e_new[i]->active) idx_new[i] = init_idx(&cr_new, &(er_new[i]));
1027  }
1028  }
1029  union_recurrent(&cr_new, e_new, er_new, idx_new, uni->sons[son & 3]);
1030  }
1031  }
1032  // no splits, recur to one son
1033  else
1034  {
1035  memcpy(&cr_new, cr, sizeof(Rect));
1036  for (i = 0; i < num; i++)
1037  {
1038  if(e[i]->active)
1039  e_new[i] = e[i];
1040  else
1041  {
1042  e_new[i] = e[i]->sons[sons[i][0] & 3];
1043  move_to_son(&(er_new[i]), er + i, sons[i][0]);
1044  if(e_new[i]->active) idx_new[i] = init_idx(&cr_new, &(er_new[i]));
1045  }
1046  }
1047  union_recurrent(&cr_new, e_new, er_new, idx_new, uni);
1048  }
1049  }
1050 
1051  delete [] e_new;
1052  delete [] er_new;
1053  delete [] sons;
1054  delete [] idx_new;
1055  }
1056 
1057  UniData** Traverse::construct_union_mesh(Mesh* unimesh)
1058  {
1059  int i;
1060  Element** e = new Element*[num];
1061  Rect* er = new Rect[num];
1062  Rect cr;
1063 
1064  this->unimesh = unimesh;
1065  unimesh->copy_base(const_cast<Mesh*>(meshes[0]));
1066 
1067  udsize = 0;
1068  unidata = new UniData*[num];
1069  memset(unidata, 0, sizeof(UniData*) * num);
1070 
1071  uint64_t* idx = new uint64_t[num];
1072  memset(idx, 0, num*sizeof(uint64_t));
1073 
1074  for (id = 0; id < meshes[0]->get_num_base_elements(); id++)
1075  {
1076  for (i = 0; i < num; i++)
1077  {
1078  e[i] = meshes[i]->get_element(id);
1079  static const Rect H2D_UNITY = { 0, 0, ONE, ONE };
1080  cr = er[i] = H2D_UNITY;
1081  }
1082  base = e[0];
1083  tri = base->is_triangle();
1084  union_recurrent(&cr, e, er, idx, unimesh->get_element(id));
1085  }
1086 
1087  delete [] e;
1088  delete [] er;
1089  delete [] idx;
1090 
1091  return unidata;
1092  }
1093  }
1094 }