MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
geometryadt.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#include "geometryadt.h"
8
9#include <algorithm>
10#include "MEMORY/collector.h"
11#include "UTIL/debug.h"
12#include "UTIL/timer.h"
13#include "geometry.h"
14#include "geometryadtnode.h"
15
16using namespace std;
17
18using namespace sortFunctions;
19
20template <MInt nDim>
22 TRACE();
23
24 m_geometry = geometry;
25 m_nodes = nullptr;
26
27 // moving boundary
28 m_mbnodes = nullptr;
29}
30
31template <MInt nDim>
33 TRACE();
34
35 delete[] m_nodes;
36
37 // moving boundary
38 delete[] m_mbnodes;
39}
40
45template <MInt nDim>
47 buildTreeNew();
48}
49
50template <MInt nDim>
52 return m_geometry->m_elements->size() * (5 * sizeof(MInt) + 2 * sizeof(MFloat)); // m_nodes[0].getStaticElementSize();
53}
54
55template <MInt nDim>
57 TRACE();
58
59 MInt noElements = m_geometry->m_elements->size();
60 // If m_nodes already allocted delete it
61 if(m_nodes) {
62 delete[] m_nodes;
63 }
64 // Create nodes
65 m_nodes = new GeometryAdtNode[mMax(noElements, 0)];
66 // Holds the start id for elements at node
67 vector<MInt> from(noElements, -1);
68 // Holds the end id for elements at node
69 vector<MInt> to(noElements, -1);
70
71 MInt currentDir = 0;
72 MInt nodeCounter = 0;
73 MInt currentNode = 0;
74 MInt currentDepth = 0;
75 // Stores the position in the idArray for the last node of the left subtree
76 MInt partitionId;
77 // Stores the current left and right subtree nodes
78 MInt left, right;
79 // Stores the id of the element connected to the current node
80 MInt currentElement;
81 // Stores the nodes that will be processed later
82
83 stack<MInt> nodeStack;
84
85 // Initialize elements member for sorting function objects
86 element<nDim>* elements = m_geometry->m_elements->a;
87
88 // Set minimum and maximum values to geometry values (bounding box)
89 copy_n(&m_geometry->m_minMax[0], 2 * nDim, &m_minMax[0]);
90
91 m_log << " Building tree the old way .." << endl << endl;
92 // Create Array with element ids, (on which the actual sorting
93 // will be performed)
94 vector<MInt>::iterator it, itFrom, itTo;
95 vector<MInt> idArray(std::max(noElements, 1));
96 MInt i = 0;
97 for(it = idArray.begin(); it != idArray.end(); it++) {
98 *it = i++;
99 }
100
101
102 // Set root node
103 m_root = 0;
104 nodeCounter = 0;
105 currentNode = m_root;
106
107 from.at(m_root) = idArray.front();
108 to.at(m_root) = idArray.back();
109 m_nodes[m_root].m_parent = -1;
110
111 // For all nodes...
112 for(;;) {
113 // Set subtree ids
115 m_nodes[currentNode].m_depth = currentDepth;
116 currentDir = currentDepth % (nDim * 2);
117 // If more than one element left...
118 if(from[currentNode] != to[currentNode]) {
119 // m_log << " -- " << " -- " << endl;
120
121 left = ++nodeCounter;
122 m_nodes[currentNode].m_leftSubtree = left;
123 m_nodes[left].m_parent = currentNode;
124
125 // If only two elements left, there is no right subtree
126 if(to[currentNode] - from[currentNode] == 1) {
127 right = 0;
128 m_nodes[currentNode].m_rightSubtree = right;
129 } else {
130 right = ++nodeCounter;
131 m_nodes[currentNode].m_rightSubtree = right;
132 m_nodes[right].m_parent = currentNode;
133 }
134 // Set from and to iterators for sorting
135 itFrom = idArray.begin();
136 itFrom += from[currentNode];
137 itTo = idArray.begin();
138 // to-iterator must point behind last element!
139 itTo += to[currentNode] + 1;
140
141 // (sort parent ids)
142 sort(itFrom, itTo, lessMinMax<nDim>(currentDir, elements));
143
144 // mTerm(1, AT_);
145 // Connect id to current node and increase from[currentNode]
146 // (for that the element won't be connected twice)
147 currentElement = idArray[from[currentNode]++];
148 m_nodes[currentNode].m_element = currentElement;
149
150
151 // find partition
152 partitionId = (MInt)((to[currentNode] - from[currentNode]) / 2 + from[currentNode]);
153 m_nodes[currentNode].m_partition = elements[idArray[partitionId]].m_minMax[currentDir];
154
155 // Set min and max values
156 m_nodes[currentNode].m_a = elements[idArray[from[currentNode] - 1]].m_minMax[currentDir];
157 m_nodes[currentNode].m_b = elements[idArray[to[currentNode]]].m_minMax[currentDir];
158
159 // Set from and to for sub-trees
160
161 // Left subtree (lower values)
162 from[left] = from[currentNode];
163 to[left] = partitionId;
164
165 // Right subtree (higher values)
166 if(right) {
167 from[right] = to[left] + 1;
168 to[right] = to[currentNode];
169 }
170 // if only one element left ...
171 } else {
172 m_nodes[currentNode].m_leftSubtree = 0;
173 m_nodes[currentNode].m_rightSubtree = 0;
174 // Connect id to leaf
175 currentElement = idArray[to[currentNode]];
176 m_nodes[currentNode].m_element = currentElement;
177 m_nodes[currentNode].m_a = elements[from[currentNode] - 1].m_minMax[currentDir];
178 m_nodes[currentNode].m_b = elements[to[currentNode]].m_minMax[currentDir];
179 }
180 // Set current dir
181
182 // writeNode(m_root);
183
184 // If left subtree exists ...
185 if(m_nodes[currentNode].m_leftSubtree) {
186 // increase depth and put rightSubtree Id on stack
187 currentDepth++;
188 if(m_nodes[currentNode].m_rightSubtree) nodeStack.push(nodeCounter);
189 // ...go left,
190 currentNode = m_nodes[currentNode].m_leftSubtree;
191
192 } else {
193 // else pop id from stack and go to id.
194 if(!nodeStack.empty()) {
195 currentNode = nodeStack.top();
196 nodeStack.pop();
197 currentDepth = m_nodes[m_nodes[currentNode].m_parent].m_depth + 1;
198 } else {
199 // Finished when empty stack and no left subtree.
200 m_log << "ok" << endl;
201 return;
202 }
203 }
204 }
205}
206
207template <MInt nDim>
209 TRACE();
210
211 // NEW_TIMER(timer1, (MChar*)"buildTree");
212
213 // START_TIMER (timer1);
214
215 MInt noElements = m_geometry->m_elements->size();
216
217 if(noElements == 1)
218 mTerm(1,
219 AT_,
220 "Apparently this method can not build an adt with just one element. I observed that in 2D but did not "
221 "debug further.");
222
223 // If m_nodes already allocted delete it
224 if(m_nodes) {
225 delete[] m_nodes;
226 }
227 // Create nodes
228
229 m_nodes = new GeometryAdtNode[mMax(noElements, 0)];
230 // Holds the start id for elements at node
231 MInt* from;
232 from = new MInt[mMax(noElements, 0)];
233
234 // Holds the end id for elements at node
235 MInt* to;
236 to = new MInt[mMax(noElements, 0)];
237
238 MInt currentDir = 0;
239 MInt nodeCounter = 0;
240 MInt currentNode = 0;
241 MInt currentDepth = 0;
242 // Stores the position in the idArray for the last node of the left subtree
243 MInt partitionId;
244 // Stores the current left and right subtree nodes
245 MInt left, right;
246 // Stores the id of the element connected to the current node
247 MInt currentElement;
248 // Stores the nodes that will be processed later
249
250 stack<MInt> nodeStack;
251
252 // Initialize elements member for sorting function objects
253 element<nDim>* elements = m_geometry->m_elements->a;
254
255 for(MInt i = 0; i < 2 * nDim; i++)
256 m_minMax[i] = m_geometry->m_minMax[i];
257
258
259 m_log << " + Building normal tree with " << noElements << " elements..." << endl;
260 // Create Array with element ids, (on which the actual sorting
261 // will be performed)
262 vector<MInt>::iterator it, itFrom, itTo;
263 vector<MInt> idArray(noElements);
264 MInt i = 0;
265 for(it = idArray.begin(); it != idArray.end(); it++)
266 *it = i++;
267
268
269 m_log << " - setting root node" << endl;
270 // Set root node
271 m_root = 0;
272 currentDir = 0;
273 nodeCounter = 0;
274 currentNode = m_root;
275
276 from[m_root] = *idArray.begin();
277 to[m_root] = *(idArray.end() - 1);
278 m_nodes[m_root].m_parent = -1;
279 m_nodes[m_root].m_depth = 0;
280
281 left = 0;
282 right = 0;
283
284 if(noElements == 1) {
285 m_nodes[m_root].m_leftSubtree = left;
286 m_nodes[m_root].m_rightSubtree = right;
287
288 // Connect id to leaf
289 currentElement = idArray[to[m_root]];
290 m_nodes[m_root].m_element = currentElement;
291 m_nodes[m_root].m_a = elements[0].m_minMax[currentDir];
292 m_nodes[m_root].m_b = elements[0].m_minMax[currentDir];
293
294 m_log << " - done building the tree" << endl;
295 return;
296 }
297
298
299 // For all nodes...
300 m_log << " - inserting other nodes" << endl;
301 nodeStack.push(m_root);
302 currentDepth = 0;
303 while(!nodeStack.empty()) {
304 currentNode = nodeStack.top();
305 nodeStack.pop();
306 currentDepth = m_nodes[currentNode].m_depth;
307 currentDir = currentDepth % (nDim * 2);
308
309 // If more than one element left...
310 if(from[currentNode] != to[currentNode]) {
311 left = ++nodeCounter;
312 m_nodes[currentNode].m_leftSubtree = left;
313 m_nodes[left].m_parent = currentNode;
314 m_nodes[left].m_depth = currentDepth + 1;
315
316 // If only two elements left, there is no right subtree
317 if(to[currentNode] - from[currentNode] == 1) {
318 right = 0;
319 m_nodes[currentNode].m_rightSubtree = right;
320 } else {
321 right = ++nodeCounter;
322 m_nodes[currentNode].m_rightSubtree = right;
323 m_nodes[right].m_parent = currentNode;
324 m_nodes[right].m_depth = currentDepth + 1;
325 nodeStack.push(right);
326 }
327 nodeStack.push(left);
328
329 // Set from and to iterators for sorting
330 itFrom = idArray.begin();
331 itFrom += from[currentNode];
332 itTo = idArray.begin();
333 // to-iterator must point behind last element!
334 itTo += to[currentNode] + 1;
335
336 // (sort parent ids)
337 sort(itFrom, itTo, lessMinMax<nDim>(currentDir, elements));
338
339 // Connect id to current node and increase from[currentNode]
340 // (for that the element won't be connected twice)
341 currentElement = idArray[from[currentNode]++];
342 m_nodes[currentNode].m_element = currentElement;
343
344 // find partition (This is actually a KDTree!!!)
345 partitionId = (MInt)((to[currentNode] - from[currentNode]) / 2 + from[currentNode]);
346 m_nodes[currentNode].m_partition = elements[idArray[partitionId]].m_minMax[currentDir];
347
348 // Set min and max values
349 m_nodes[currentNode].m_a = elements[idArray[from[currentNode] - 1]].m_minMax[currentDir];
350 m_nodes[currentNode].m_b = elements[idArray[to[currentNode]]].m_minMax[currentDir];
351
352 // Set from and to for sub-trees
353
354 // Left subtree (lower values)
355 from[left] = from[currentNode];
356 to[left] = partitionId;
357
358 // Right subtree (higher values)
359 if(right) {
360 from[right] = to[left] + 1;
361 to[right] = to[currentNode];
362 }
363 // if only one element left ...
364 } else {
365 right = 0;
366 left = 0;
367 m_nodes[currentNode].m_leftSubtree = left;
368 m_nodes[currentNode].m_rightSubtree = right;
369
370 // Connect id to leaf
371 currentElement = idArray[to[currentNode]];
372 m_nodes[currentNode].m_element = currentElement;
373 m_nodes[currentNode].m_a = elements[from[currentNode] - 1].m_minMax[currentDir];
374 m_nodes[currentNode].m_b = elements[to[currentNode]].m_minMax[currentDir];
375 }
376 // Set current dir
377
378 // writeNode(m_root);
379 }
380
381 m_log << " - done building the tree" << endl;
382 // for(MInt k = 0; k < 10; k++) writeNode(k);
383 delete[] from;
384 delete[] to;
385}
386
387template <MInt nDim>
389 m_log << " - Node : " << node << endl;
390 m_log << "parent : " << m_nodes[node].m_parent << endl;
391 m_log << "partition : " << m_nodes[node].m_partition << endl;
392 m_log << "leftSubtree : " << m_nodes[node].m_leftSubtree << endl;
393 m_log << "rightSubtree: " << m_nodes[node].m_rightSubtree << endl;
394 m_log << "depth : " << m_nodes[node].m_depth << endl;
395 m_log << "a : " << m_nodes[node].m_a << endl;
396 m_log << "b : " << m_nodes[node].m_b << endl;
397}
398
411// TODO labels:GEOM,DLB optimize further? is a major time consumer during FV initSolutionStep during DLB
412template <MInt nDim>
413void GeometryAdt<nDim>::retrieveNodes(MFloat* targetRegion, std::vector<MInt>& nodeList) const {
414 // TRACE();
415
416 MInt noElements = m_geometry->m_elements->size();
417 if(noElements == 0) {
418 return;
419 }
420
421 // 2-D Mapping
422 ASSERT(nodeList.empty(), "NodeList is not empty!");
423 MFloat t_min[2 * MAX_SPACE_DIMENSIONS];
424 MFloat t_max[2 * MAX_SPACE_DIMENSIONS];
425
426 // t_min: min(bounding box: x, y, z), min(target: x, y, z)
427 // t_max: max(target: x, y, z), max(bounding box: x, y, z)
428 for(MInt i = 0; i < nDim; i++) {
429 t_min[i] = m_minMax[i];
430 t_min[i + nDim] = targetRegion[i];
431 t_max[i] = targetRegion[i + nDim];
432 t_max[i + nDim] = m_minMax[i + nDim];
433 }
434
435 // Init empty stack and start at first node
436 MInt root = 0;
437 stack<MInt> subtreeStack;
438
439 // Infinite loop until complete tree is traversed
440 for(;;) {
441 // Check if the current nodes element-bounding box intersects target region
442 const MInt currentElementId = m_nodes[root].m_element;
443 const MFloat* const minMax = m_geometry->m_elements->a[currentElementId].m_minMax;
444 MBool doesOverlap = true;
445
446 for(MInt i = 0; i < 2 * nDim; i++)
447 if(minMax[i] > t_max[i] || minMax[i] < t_min[i]) {
448 doesOverlap = false;
449 break;
450 }
451
452 // Inside target domain => add current element to return list
453 if(doesOverlap) {
454 nodeList.push_back(currentElementId);
455 }
456
457 const MInt currentDir = m_nodes[root].m_depth % (2 * nDim);
458
459 // if right subtree is inside target domain push on stack
460 const MInt right = m_nodes[root].m_rightSubtree;
461 if(right > 0 && m_nodes[root].m_b >= t_min[currentDir] && m_nodes[root].m_partition <= t_max[currentDir])
462 subtreeStack.push(right);
463
464 // if left subtree is inside target domain set it as root
465 const MInt left = m_nodes[root].m_leftSubtree;
466 if(left > 0 && m_nodes[root].m_partition >= t_min[currentDir] && m_nodes[root].m_a <= t_max[currentDir]) {
467 root = left;
468 continue;
469 }
470
471 if(subtreeStack.empty()) {
472 return;
473 } else {
474 root = subtreeStack.top();
475 subtreeStack.pop();
476 }
477 }
478}
479
480
481template <MInt nDim>
483 TRACE();
484
485 // Write dx output (intersected triangles)
486 stringstream filename;
487 // Write dx output (all triangles)
488 filename.str("");
489 filename << "dxOut_all";
490 filename << ".dx";
491 ofstream ofl(filename.str().c_str());
492 // ofl.open(filename.str().c_str());
493 ofl << "object 1 class array type float rank 1 shape 3 items " << m_geometry->m_noElements * nDim << " data follows"
494 << endl;
495 for(MInt i = 0; i < m_geometry->m_noElements; i++) {
496 for(MInt j = 0; j < nDim; j++) {
497 for(MInt k = 0; k < nDim; k++) {
498 ofl << m_geometry->m_elements->a[i].m_vertices[j][k] << " ";
499 }
500 ofl << endl;
501 }
502 }
503 ofl << "object 2 class array type int rank 1 shape 3 items " << m_geometry->m_noElements << " data follows" << endl;
504 MInt c = 0;
505 for(MInt i = 0; i < m_geometry->m_noElements; i++) {
506 for(MInt j = 0; j < nDim; j++) {
507 ofl << c++ << " ";
508 }
509 ofl << endl;
510 }
511 ofl << R"(attribute "element type" string "triangles")" << endl;
512 ofl << R"(attribute "ref" string "positions")" << endl;
513
514 ofl << "object 3 class array type float rank 0 items " << m_geometry->m_noElements * 3 << " data follows" << endl;
515 c = 0;
516 for(MInt i = 0; i < m_geometry->m_noElements; i++) {
517 for(MInt j = 0; j < nDim; j++) {
518 ofl << c << " ";
519 }
520 c++;
521 ofl << endl;
522 }
523 ofl << R"(attribute "dep" string "positions")" << endl;
524
525 ofl << "object \"irregular positions irregular connections\" class field" << endl;
526 ofl << "component \"positions\" value 1" << endl;
527 ofl << "component \"connections\" value 2" << endl;
528 ofl << "component \"data\" value 3" << endl;
529 ofl << "" << endl;
530 ofl.close();
531}
532
533
534template <MInt nDim>
535void GeometryAdt<nDim>::splitTree(MInt /*noSubTrees*/) {
536 /*
537 geometryPropertyMap* pMap;
538 string fileName = "NCTEST";
539
540 GeometryIONetcdf* geometryIOBase = new GeometryIONetcdf;
541 // geometryIOBase->writeProperties((MChar*)fileName.c_str(), pMap);
542
543
544
545
546 NcFile file(fileName.c_str(), NcFile::Replace);
547 NcVar* tmpVar;
548 NcDim* tmpDim;
549 MString dimName;
550
551 dimName = "nDim";
552 tmpDim = file.add_dim(dimName.c_str(), nDim);
553
554 dimName = "noPointsPerVertex";
555 tmpDim = file.add_dim(dimName.c_str(), 3);
556
557 dimName = "noVertices";
558 tmpDim = file.add_dim(dimName.c_str(), 3);
559
560 dimName = "noNodes";
561 tmpDim = file.add_dim(dimName.c_str(), 3);
562
563 dimName = "noChildIds";
564 tmpDim = file.add_dim(dimName.c_str(), 3);
565 */
566
567 /*
568 for( propertyMap::iterator i = pMap->begin(); i!=pMap->end(); i++) {
569 dimName = i->first;
570 switch( i->second->type() )
571 {
572 case INT:
573 {
574 if ( i->second->count() > 1 ){
575 dimName.append("Dim");
576 tmpDim = file.add_dim( dimName.c_str(), i->second->count());
577 tmpVar = file.add_var(i->first.c_str(), ncInt, tmpDim);
578 tmpVar->put(i->second->intField, i->second->count());
579 }
580 else {
581 tmpVar = file.add_var(i->first.c_str(), ncInt, 0);
582 tmpVar->put(i->second->intField, 1);
583 }
584 break;
585 }
586
587 case FLOAT:
588 {
589 if ( i->second->count() > 1 ){
590 dimName.append("Dim");
591 tmpDim = file.add_dim( dimName.c_str(), i->second->count());
592 tmpVar = file.add_var(i->first.c_str(), ncDouble, tmpDim);
593 tmpVar->put(i->second->floatField, i->second->count());
594 }
595 else {
596 tmpVar = file.add_var(i->first.c_str(), ncDouble, 0);
597 tmpVar->put(i->second->floatField, 1);
598 }
599 break;
600 }
601
602 case STRING:
603 {
604 if ( i->second->stringField[0].length() > 1 ){
605 dimName.append("Dim");
606 tmpDim = file.add_dim( dimName.c_str(), i->second->stringField[0].length());
607 tmpVar = file.add_var(i->first.c_str(), ncChar, tmpDim);
608 tmpVar->put(i->second->stringField[0].c_str(), i->second->stringField[0].length());
609 }
610 else {
611 tmpVar = file.add_var(i->first.c_str(), ncChar, 0);
612 tmpVar->put(i->second->stringField[0].c_str(), 1);
613 }
614 break;
615 }
616
617 default:
618 {
619 break;
620 }
621 }
622 }
623 */
624}
625
626
627template <MInt nDim>
629 TRACE();
630 /*
631 //TAN FIX
632 // NEW_TIMER(timer1, (MChar*)"buildTreeMB");
633 // START_TIMER (timer1);
634 MInt noMBElements = m_geometry->m_mbelements->size();
635 // If m_mbnodes already allocted delete it
636 if(m_mbnodes){
637 delete [] m_mbnodes;
638 }
639 // Create nodes
640 m_mbnodes = new GeometryAdtNode[noMBElements];
641 // Holds the start id for elements at node
642 MInt *from;
643 from = new MInt[noMBElements];
644 // Holds the end id for elements at node
645 MInt *to;
646 to = new MInt[noMBElements];
647 MInt currentDir = 0;
648 MInt nodeCounter = 0;
649 MInt currentNode = 0;
650 MInt currentDepth = 0;
651 // Stores the position in the idArray for the last node of the left subtree
652 MInt partitionId;
653 // Stores the current left and right subtree nodes
654 MInt left, right;
655 // Stores the id of the element connected to the current node
656 MInt currentElement;
657 // Stores the nodes that will be processed later
658
659 stack <MInt> nodeStack;
660
661 // Initialize elements member for sorting function objects
662 element* mbelements = m_geometry->m_mbelements->a;
663 lessMinMax<nDim>::m_mbelements = mbelements;
664
665 if(m_mbminMax) {delete [] m_mbminMax;}
666 m_mbminMax = new MFloat[2*nDim];
667 for(MInt i=0; i < 2*nDim; i ++){
668 m_mbminMax[i] = m_geometry->m_mbminMax[i];
669 }
670
671 m_log << " Building tree...";
672 // Create Array with element ids, (on which the actual sorting
673 // will be performed)
674 vector <MInt>::iterator it, itFrom, itTo;
675 vector <MInt> idArray (noMBElements);
676 MInt i=0;
677 for (it = idArray.begin(); it!=idArray.end(); it++){
678 *it=i++;
679 }
680
681 // Set root node
682 m_root = 0;
683 currentDir = 0;
684 nodeCounter = 0;
685 currentNode = m_root;
686
687 from[m_root] = *idArray.begin();
688 to[m_root] = *(idArray.end()-1);
689 m_mbnodes[m_root].m_parent=-1;
690 left = 0;
691 right = 0;
692 // For all nodes...
693
694 for(;;){
695 // Set subtree ids
697 m_mbnodes[currentNode].m_depth = currentDepth;
698 currentDir = currentDepth % (nDim * 2);
699 lessMinMax<nDim>::m_dir = currentDir;
700 // If more than one element left...
701 if(from[currentNode] != to[currentNode]){
702 // m_log << " -- " << " -- " << endl;
703
704 left=++nodeCounter;
705 m_mbnodes[currentNode].m_leftSubtree=left;
706 m_mbnodes[ left ].m_parent = currentNode;
707
708 // If only two elements left, there is no right subtree
709 if(to[currentNode] - from[currentNode] == 1 ){
710 right=0;
711 m_mbnodes[currentNode].m_rightSubtree = right;
712 }else{
713 right=++nodeCounter;
714 m_mbnodes[currentNode].m_rightSubtree = right;
715 m_mbnodes[right].m_parent = currentNode;
716 }
717 // Set from and to iterators for sorting
718 itFrom = idArray.begin();
719 itFrom += from[currentNode];
720 itTo = idArray.begin();
721 // to-iterator must point behind last element!
722 itTo += to[currentNode] + 1;
723
724 // (sort parent ids)
725 sort(itFrom, itTo,lessMinMax<nDim>::mbcomp);
726
727 // mTerm(1, AT_);
728 // Connect id to current node and increase from[currentNode]
729 // (for that the element won't be connected twice)
730 currentElement = idArray[from[currentNode]++];
731 m_mbnodes[currentNode].m_element = currentElement;
732
733 // find partition
734 partitionId = (MInt)((to[currentNode] - from[currentNode]) / 2 + from[currentNode] );
735 m_mbnodes[currentNode].m_partition = mbelements[idArray[partitionId]].m_minMax[currentDir];
736
737 // Set min and max values
738 m_mbnodes[currentNode].m_a = mbelements[idArray[from[currentNode] - 1]].m_minMax[currentDir];
739 m_mbnodes[currentNode].m_b = mbelements[idArray[to[currentNode]]].m_minMax[currentDir];
740
741 // Set from and to for sub-trees
742
743 // Left subtree (lower values)
744 from[left] = from[currentNode];
745 to[left] = partitionId;
746
747 // Right subtree (higher values)
748 if(right){
749 from[right] = to[left] + 1;
750 to[right] = to[currentNode];
751 }
752 // if only one element left ...
753 }else{
754 m_mbnodes[currentNode].m_leftSubtree=0;
755 m_mbnodes[currentNode].m_rightSubtree=0;
756 // Connect id to leaf
757 currentElement = idArray[to[currentNode]];
758 m_mbnodes[currentNode].m_element = currentElement;
759 m_mbnodes[currentNode].m_a = mbelements[from[currentNode] - 1].m_minMax[currentDir];
760 m_mbnodes[currentNode].m_b = mbelements[to[currentNode]].m_minMax[currentDir];
761
762 }
763 // Set current dir
764
765 // writeNode(m_root);
766
767 // If left subtree exists ...
768 if( m_mbnodes[currentNode].m_leftSubtree ){
769 // increase depth and put rightSubtree Id on stack
770 currentDepth++;
771 if(m_mbnodes[currentNode].m_rightSubtree)
772 nodeStack.push(nodeCounter);
773 // ...go left,
774 currentNode = m_mbnodes[currentNode].m_leftSubtree;
775
776 }else{
777 // else pop id from stack and go to id.
778 if(!nodeStack.empty()){
779 currentNode = nodeStack.top();
780 nodeStack.pop();
781 currentDepth = m_mbnodes[m_mbnodes[currentNode].m_parent].m_depth + 1;
782 }else{
783 // Finished when empty stack and no left subtree.
784 m_log << "ok" << endl;
785 //TAN FIXED
786 delete []from;
787 delete []to;
788 return;
789 }
790 }
791 }*/
792
793 m_log << "geometry m_elements size = ";
794 m_log << m_geometry->m_elements->size() << endl;
795
796 MInt noMBElements = m_geometry->m_mbelements->size();
797 // If m_mbnodes already allocted delete it
798
799 if(m_mbnodes) {
800 delete[] m_mbnodes;
801 }
802 // Create nodes
803
804 m_mbnodes = new GeometryAdtNode[mMax(noMBElements, 0)];
805 // Holds the start id for elements at node
806 vector<MInt> from(noMBElements, -1);
807 // Holds the end id for elements at node
808 vector<MInt> to(noMBElements, -1);
809
810 MInt currentDir = 0;
811 MInt nodeCounter = 0;
812 MInt currentNode = 0;
813 MInt currentDepth = 0;
814 // Stores the position in the idArray for the last node of the left subtree
815 MInt partitionId;
816 // Stores the current left and right subtree nodes
817 MInt left, right;
818 // Stores the id of the element connected to the current node
819 MInt currentElement;
820 // Stores the nodes that will be processed later
821
822 stack<MInt> nodeStack;
823
824 // Initialize elements member for sorting function objects
825 element<nDim>* elements = m_geometry->m_mbelements->a;
826
827 for(MInt i = 0; i < 2 * nDim; i++) {
828 m_mbminMax[i] = m_geometry->m_mbminMax[i];
829 }
830
831 m_log << " + Building MB tree with " << noMBElements << " elements..." << endl << endl;
832 // Create Array with element ids, (on which the actual sorting
833 // will be performed)
834 vector<MInt>::iterator it, itFrom, itTo;
835 vector<MInt> idArray(std::max(noMBElements, 1));
836 MInt i = 0;
837 for(it = idArray.begin(); it != idArray.end(); it++) {
838 *it = i++;
839 }
840
841 // Set root node
842 m_root = 0;
843 currentDir = 0;
844 nodeCounter = 0;
845 currentNode = m_root;
846
847 from.at(m_root) = idArray.front();
848 to.at(m_root) = idArray.back();
849 m_mbnodes[m_root].m_parent = -1;
850 m_mbnodes[m_root].m_depth = 0;
851
852 left = 0;
853 right = 0;
854 // For all nodes...
855
856 nodeStack.push(m_root);
857 currentDepth = 0;
858
859 while(!nodeStack.empty()) {
860 currentNode = nodeStack.top();
861 nodeStack.pop();
862 currentDepth = m_mbnodes[currentNode].m_depth;
863 currentDir = currentDepth % (nDim * 2);
864
865 // If more than one element left...
866 if(from[currentNode] != to[currentNode]) {
867 left = ++nodeCounter;
868 m_mbnodes[currentNode].m_leftSubtree = left;
869 m_mbnodes[left].m_parent = currentNode;
870 m_mbnodes[left].m_depth = currentDepth + 1;
871
872 // If only two elements left, there is no right subtree
873 if(to[currentNode] - from[currentNode] == 1) {
874 right = 0;
875 m_mbnodes[currentNode].m_rightSubtree = right;
876 } else {
877 right = ++nodeCounter;
878 m_mbnodes[currentNode].m_rightSubtree = right;
879 m_mbnodes[right].m_parent = currentNode;
880 m_mbnodes[right].m_depth = currentDepth + 1;
881 nodeStack.push(right);
882 }
883 nodeStack.push(left);
884
885 // Set from and to iterators for sorting
886 itFrom = idArray.begin();
887 itFrom += from[currentNode];
888 itTo = idArray.begin();
889 // to-iterator must point behind last element!
890 itTo += to[currentNode] + 1;
891
892 // (sort parent ids)
893 sort(itFrom, itTo, lessMinMax<nDim>(currentDir, elements));
894
895 // Connect id to current node and increase from[currentNode]
896 // (for that the element won't be connected twice)
897 currentElement = idArray[from[currentNode]++];
898 m_mbnodes[currentNode].m_element = currentElement;
899
900
901 // find partition (This is actually a KDTree!!!)
902 partitionId = (MInt)((to[currentNode] - from[currentNode]) / 2 + from[currentNode]);
903 m_mbnodes[currentNode].m_partition = elements[idArray[partitionId]].m_minMax[currentDir];
904
905 // Set min and max values
906 m_mbnodes[currentNode].m_a = elements[idArray[from[currentNode] - 1]].m_minMax[currentDir];
907 m_mbnodes[currentNode].m_b = elements[idArray[to[currentNode]]].m_minMax[currentDir];
908
909 // Set from and to for sub-trees
910
911 // Left subtree (lower values)
912 from[left] = from[currentNode];
913 to[left] = partitionId;
914
915 // Right subtree (higher values)
916 if(right) {
917 from[right] = to[left] + 1;
918 to[right] = to[currentNode];
919 }
920 // if only one element left ...
921 } else {
922 right = 0;
923 left = 0;
924 m_mbnodes[currentNode].m_leftSubtree = left;
925 m_mbnodes[currentNode].m_rightSubtree = right;
926 // Connect id to leaf
927 currentElement = idArray[to[currentNode]];
928 m_mbnodes[currentNode].m_element = currentElement;
929 m_mbnodes[currentNode].m_a = elements[from[currentNode] - 1].m_minMax[currentDir];
930 m_mbnodes[currentNode].m_b = elements[to[currentNode]].m_minMax[currentDir];
931 }
932 }
933
934 m_log << "ok" << endl;
935}
936
937template <MInt nDim>
938void GeometryAdt<nDim>::retrieveNodesMBElements(const MFloat* targetRegion, std::vector<MInt>& nodeList) const {
939 // TRACE();
940
941 // 2-D Mapping
942 MFloat* t_min;
943 MFloat* t_max;
944 MFloat* x;
945 MBool doesOverlap;
946 ASSERT(nodeList.empty(), "NodeList is not empty!");
947
948 t_min = new MFloat[2 * nDim];
949 t_max = new MFloat[2 * nDim];
950 x = new MFloat[2 * nDim];
951 for(MInt i = 0; i < nDim; i++) {
952 t_min[i] = m_mbminMax[i];
953 t_min[i + nDim] = targetRegion[i];
954 t_max[i] = targetRegion[i + nDim];
955 t_max[i + nDim] = m_mbminMax[i + nDim];
956 }
957
958 MInt currentDir;
959 GeometryElement<nDim>* currentElement;
960 GeometryElement<nDim>* mbelements = m_geometry->m_mbelements->a;
961 MInt currentElementId;
962 MInt root;
963 MInt left, right;
964 root = 0;
965 MInt searchedNodes = 0;
966 stack<MInt> subtreeStack;
967 for(;;) {
968 currentDir = m_mbnodes[root].m_depth % (2 * nDim);
969 currentElementId = m_mbnodes[root].m_element;
970 currentElement = &mbelements[currentElementId];
971
972 // m_log << " Searching node " << root << endl;
973 searchedNodes++;
974 // Check if the current nodes element-bounding box intersects the target region
975 doesOverlap = true;
976 for(MInt i = 0; i < 2 * nDim; i++) {
977 if(currentElement->m_minMax[i] <= t_max[i] && currentElement->m_minMax[i] >= t_min[i]) {
978 } else {
979 doesOverlap = false;
980 break;
981 }
982 }
983
984 if(doesOverlap) {
985 // Inside target domain => add current element to return list
986 nodeList.push_back(currentElementId);
987 // m_log << " Found intersection candidate " << currentElementId << endl;
988 }
989 // if right subtree is inside target domain push on stack
990 right = m_mbnodes[root].m_rightSubtree;
991 if(right) {
992 if(m_mbnodes[root].m_b >= t_min[currentDir] && m_mbnodes[root].m_partition <= t_max[currentDir])
993 subtreeStack.push(right);
994 }
995 // if left subtree is inside target domain set it as root
996 left = m_mbnodes[root].m_leftSubtree;
997 if(left) {
998 if(m_mbnodes[root].m_partition >= t_min[currentDir] && m_mbnodes[root].m_a <= t_max[currentDir]) {
999 root = left;
1000 continue;
1001 }
1002 }
1003 if(subtreeStack.empty()) {
1004 delete[] x;
1005 delete[] t_min;
1006 delete[] t_max;
1007
1008 return;
1009 } else {
1010 root = subtreeStack.top();
1011 subtreeStack.pop();
1012 }
1013 }
1014}
1015
1016template <MInt nDim>
1018 return m_root;
1019}
1020
1021// Explicit instantiations for 2D and 3D
1022template class GeometryAdt<2>;
1023template class GeometryAdt<3>;
void retrieveNodes(MFloat *targetRegion, std::vector< MInt > &nodeList) const
retrieves the nodes that intersect with a given target bounding box
void retrieveNodesMBElements(const MFloat *targetRegion, std::vector< MInt > &nodeList) const
GeometryAdt(const Geometry< nDim > *geometry)
Definition: geometryadt.cpp:21
void writeTreeToDx()
void buildTreeNew()
void buildTree()
Create an ADT from the geometry.
Definition: geometryadt.cpp:46
void buildTreeMB()
void splitTree(MInt noSubTrees)
MLong memoryUsage()
Definition: geometryadt.cpp:51
void buildTreeOld()
Definition: geometryadt.cpp:56
void writeNode(MInt node)
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62
double MFloat
Definition: maiatypes.h:52
int64_t MLong
Definition: maiatypes.h:64
bool MBool
Definition: maiatypes.h:58