Loading...
Searching...
No Matches
Octant.cpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25// =================================================================================== //
26// INCLUDES //
27// =================================================================================== //
28#include "Octant.hpp"
29#include "morton.hpp"
30
31#include <algorithm>
32#include <cassert>
33#include <cmath>
34#include <iostream>
35
36namespace bitpit {
37
46IBinaryStream& operator>>(IBinaryStream &buffer, Octant &octant)
47{
48 uint8_t dimensions;
49 buffer >> dimensions;
50
51 uint8_t level;
52 buffer >> level;
53
54 octant.initialize(dimensions, level, true);
55
56 buffer >> octant.m_morton;
57
58 buffer >> octant.m_marker;
59
60 buffer >> octant.m_ghost;
61
62 for(int i = 0; i < Octant::INFO_ITEM_COUNT; ++i){
63 bool value;
64 buffer >> value;
65 octant.m_info[i] = value;
66 }
67
68 return buffer;
69}
70
79OBinaryStream& operator<<(OBinaryStream &buffer, const Octant &octant)
80{
81 buffer << octant.m_dim;
82 buffer << octant.m_level;
83
84 buffer << octant.m_morton;
85
86 buffer << octant.m_marker;
87
88 buffer << octant.m_ghost;
89
90 for(int i = 0; i < Octant::INFO_ITEM_COUNT; ++i){
91 buffer << (bool) octant.m_info[i];
92 }
93
94 return buffer;
95}
96
97// =================================================================================== //
98// NAME SPACES //
99// =================================================================================== //
100using namespace std;
101
102// =================================================================================== //
103// CLASS IMPLEMENTATION //
104// =================================================================================== //
105
106// =================================================================================== //
107// STATIC AND CONSTANT
108// =================================================================================== //
109
110const TreeConstants::Instances Octant::sm_treeConstants = TreeConstants::instances();
111
112// =================================================================================== //
113// CONSTRUCTORS AND OPERATORS
114// =================================================================================== //
115
119 initialize();
120};
121
126Octant::Octant(uint8_t dim){
127 initialize(dim, 0, true);
128};
129
136Octant::Octant(uint8_t dim, uint8_t level, uint64_t morton){
137 initialize(dim, level, true);
138
139 // Set the morton
140 m_morton = morton;
141
142};
143
152Octant::Octant(uint8_t dim, uint8_t level, int32_t x, int32_t y, int32_t z){
153 initialize(dim, level, true);
154
155 // Set the morton
156 m_morton = PABLO::computeMorton(m_dim, x, y, z);
157
158};
159
169Octant::Octant(bool bound, uint8_t dim, uint8_t level, int32_t x, int32_t y, int32_t z){
170 initialize(dim, level, bound);
171
172 // Set the morton
173 m_morton = PABLO::computeMorton(m_dim, x, y, z);
174
175};
176
179bool Octant::operator ==(const Octant & oct2){
180 bool check = true;
181 check = check && (m_dim == oct2.m_dim);
182 check = check && (m_morton == oct2.m_morton);
183 check = check && (m_level == oct2.m_level);
184 return check;
185}
186
187// =================================================================================== //
188// METHODS
189// =================================================================================== //
190
193void
194Octant::initialize() {
195 initialize(0, 0, false);
196}
197
203void
204Octant::initialize(uint8_t dim, uint8_t level, bool bound) {
205 m_dim = dim;
206 m_level = level;
207
208 // Reset the marker
209 m_marker = 0;
210
211 // Reset the morton
212 m_morton = 0;
213
214 // Initialize octant info
215 m_info.reset();
216 m_info[OctantInfo::INFO_BALANCED] = true;
217 m_ghost = -1;
218
219 // If this is the root octant we need to set the boundary condition bound
220 // for faces
221 if (m_dim >= 2 && m_level == 0) {
222 uint8_t nf = m_dim*2;
223 for (uint8_t i=0; i<nf; i++){
224 m_info[i] = bound;
225 }
226 }
227};
228
229// =================================================================================== //
230// BASIC GET/SET METHODS
231// =================================================================================== //
232
236uint32_t
237Octant::getDim() const{return m_dim;};
238
242u32array3
246
250uint32_t
252 return PABLO::computeCoordinate(m_dim, m_morton, coord);
253};
254
258uint8_t
259Octant::getLevel() const{return m_level;};
260
264int8_t
265Octant::getMarker() const{return m_marker;};
266
271bool
272Octant::getBound(uint8_t face) const{
273 return (m_info[OctantInfo::INFO_BOUNDFACE0 + face]);
274};
275
280bool
281Octant::getEdgeBound(uint8_t edge) const{
282 for (int face : sm_treeConstants[m_dim].edgeFace[edge]) {
283 if (getBound(face)) {
284 return true;
285 }
286 }
287
288 return false;
289};
290
295bool
296Octant::getNodeBound(uint8_t node) const{
297 for (int face : sm_treeConstants[m_dim].nodeFace[node]) {
298 if (getBound(face)) {
299 return true;
300 }
301 }
302
303 return false;
304};
305
309bool
311 for (int i = 0; i < sm_treeConstants[m_dim].nFaces; ++i) {
312 if (getBound(i)) {
313 return true;
314 }
315 }
316
317 return false;
318};
319
323void
324Octant::setBound(uint8_t face) {
325 m_info[INFO_BOUNDFACE0 + face] = true;
326};
327
332bool
333Octant::getPbound(uint8_t face) const{
334 return m_info[INFO_PBOUNDFACE0 + face];
335};
336
340bool
342 for (int i = 0; i < sm_treeConstants[m_dim].nFaces; ++i) {
343 if (getPbound(i)) {
344 return true;
345 }
346 }
347
348 return false;
349};
350
354bool
355Octant::getIsNewR() const{return m_info[OctantInfo::INFO_NEW4REFINEMENT];};
356
360bool
361Octant::getIsNewC() const{return m_info[OctantInfo::INFO_NEW4COARSENING];};
362
366bool
367Octant::getIsGhost() const{return (m_ghost >= 0);};
368
372int
373Octant::getGhostLayer() const{return m_ghost;};
374
378bool
379Octant::getBalance() const{return (m_info[OctantInfo::INFO_BALANCED]);};
380
384void
385Octant::setMarker(int8_t marker){
386 this->m_marker = marker;
387};
388
392void
393Octant::setBalance(bool balance){
394 m_info[OctantInfo::INFO_BALANCED] = balance;
395};
396
400void
401Octant::setLevel(uint8_t level){
402 this->m_level = level;
403};
404
409void
410Octant::setPbound(uint8_t face, bool flag){
411 m_info[INFO_PBOUNDFACE0 + face] = flag;
412};
413
418void
419Octant::setGhostLayer(int ghostLayer){
420 m_ghost = ghostLayer;
421};
422
423
424// =================================================================================== //
425// OTHER GET/SET METHODS
426// =================================================================================== //
427
431uint32_t
433 return sm_treeConstants[m_dim].lengths[m_level];
434};
435
439uint64_t
441 return sm_treeConstants[m_dim].areas[m_level];
442};
443
447uint64_t
449 return sm_treeConstants[m_dim].volumes[m_level];
450};
451
452// =================================================================================== //
453
457darray3
459 double dh = double(getLogicalSize())*0.5;
460 darray3 center = {{0., 0., 0.}};
461 center[0] = getLogicalCoordinates(0) + dh;
462 center[1] = getLogicalCoordinates(1) + dh;
463 center[2] = getLogicalCoordinates(2) + double(m_dim-2)*dh;
464 return center;
465};
466
467// =================================================================================== //
468
473darray3
474Octant::getLogicalFaceCenter(uint8_t iface) const{
475 assert(iface < m_dim*2);
476
477 double dh_2 = double(getLogicalSize())*0.5;
478 darray3 center = {{0., 0., 0.}};
479 center[0] = getLogicalCoordinates(0) + (double)sm_treeConstants[m_dim].faceDisplacements[iface][0] * dh_2;
480 center[1] = getLogicalCoordinates(1) + (double)sm_treeConstants[m_dim].faceDisplacements[iface][1] * dh_2;
481 center[2] = getLogicalCoordinates(2) + double(m_dim-2) * (double)sm_treeConstants[m_dim].faceDisplacements[iface][2] * dh_2;
482
483 return center;
484};
485
486// =================================================================================== //
487
492darray3
493Octant::getLogicalEdgeCenter(uint8_t iedge) const{
494 double dh_2;
495 darray3 center = {{0., 0., 0.}};
496
497 dh_2 = double(getLogicalSize())*0.5;
498 center[0] = getLogicalCoordinates(0) + (double)sm_treeConstants[m_dim].edgeDisplacements[iedge][0] * dh_2;
499 center[1] = getLogicalCoordinates(1) + (double)sm_treeConstants[m_dim].edgeDisplacements[iedge][1] * dh_2;
500 center[2] = getLogicalCoordinates(2) + double(m_dim-2) * (double)sm_treeConstants[m_dim].edgeDisplacements[iedge][2] * dh_2;
501 return center;
502};
503
504// =================================================================================== //
505
509void
510Octant::getLogicalNodes(u32arr3vector & nodes) const{
511 uint8_t i;
512 uint32_t dh;
513 uint8_t nn = uint8_t(1)<<m_dim;
514
515 dh = getLogicalSize();
516 nodes.resize(nn);
517
518 u32array3 coords = getLogicalCoordinates();
519
520 for (i = 0; i < nn; i++){
521 nodes[i][0] = coords[0] + uint32_t(sm_treeConstants[m_dim].nodeCoordinates[i][0])*dh;
522 nodes[i][1] = coords[1] + uint32_t(sm_treeConstants[m_dim].nodeCoordinates[i][1])*dh;
523 nodes[i][2] = coords[2] + uint32_t(sm_treeConstants[m_dim].nodeCoordinates[i][2])*dh;
524 }
525};
526
530u32arr3vector
532 u32arr3vector nodes;
533 getLogicalNodes(nodes);
534 return nodes;
535};
536
541void Octant::getLogicalNode(u32array3 & node, uint8_t inode) const{
542 uint32_t dh;
543
544 dh = getLogicalSize();
545
546 node = getLogicalCoordinates();
547
548 node[0] += sm_treeConstants[m_dim].nodeCoordinates[inode][0]*dh;
549 node[1] += sm_treeConstants[m_dim].nodeCoordinates[inode][1]*dh;
550 node[2] += sm_treeConstants[m_dim].nodeCoordinates[inode][2]*dh;
551
552};
553
558u32array3 Octant::getLogicalNode(uint8_t inode) const{
559 u32array3 node;
560 getLogicalNode(node, inode);
561 return node;
562};
563
569void Octant::getNormal(uint8_t iface, i8array3 & normal, const int8_t (&normals)[6][3]) const{
570 uint8_t i;
571 for (i = 0; i < 3; i++){
572 normal[i] = normals[iface][i];
573 }
574};
575
576
580uint64_t Octant::getMorton() const{
581 return m_morton;
582};
583
588 u32array3 lastDescCoordinates = computeLastDescCoordinates();
589 return PABLO::computeMorton(m_dim, lastDescCoordinates[0], lastDescCoordinates[1], lastDescCoordinates[2]);
590};
591
598 u32array3 lastDescCoords = getLogicalCoordinates();
599 for (int i=0; i<m_dim; i++){
600 lastDescCoords[i] += (uint32_t(1) << (sm_treeConstants[m_dim].maxLevel - m_level)) - 1;
601 }
602
603 return lastDescCoords;
604};
605
610 u32array3 fatherCoordinates = computeFatherCoordinates();
611 return PABLO::computeMorton(m_dim, fatherCoordinates[0], fatherCoordinates[1], fatherCoordinates[2]);
612};
613
620 u32array3 fatherCoordinates = getLogicalCoordinates();
621 for (int i=0; i<m_dim; i++){
622 fatherCoordinates[i] -= fatherCoordinates[i]%(uint32_t(1) << (sm_treeConstants[m_dim].maxLevel - max(0,(m_level-1))));
623 }
624 return fatherCoordinates;
625};
626
635uint64_t Octant::computeNodePersistentKey(uint8_t inode) const{
636
637 u32array3 node = getLogicalNode(inode);
638
639 return computeNodePersistentKey(node);
640};
641
650uint64_t Octant::computeNodePersistentKey(const u32array3 &node) const{
651
652 return PABLO::computeXYZKey(m_dim, node[0], node[1], node[2]);
653};
654
659{
660 unsigned int binarySize = 0;
661 binarySize += sizeof(uint8_t); // dimensions
662 binarySize += sizeof(uint8_t); // level
663 binarySize += sizeof(uint64_t); // morton
664 binarySize += sizeof(int8_t); // marker
665 binarySize += sizeof(int); // ghost layer
666 binarySize += INFO_ITEM_COUNT * sizeof(bool); // info
667
668 return binarySize;
669}
670
671// =================================================================================== //
672// OTHER METHODS
673// =================================================================================== //
674
679 uint64_t lastDescMorton = computeLastDescMorton();
680 Octant lastDesc(m_dim, sm_treeConstants[m_dim].maxLevel, lastDescMorton);
681 return lastDesc;
682};
683
684// =================================================================================== //
685
690 uint64_t fatherMorton = computeFatherMorton();
691 Octant father(m_dim, max(0,m_level-1), fatherMorton);
692 return father;
693};
694
695// =================================================================================== //
696
700uint8_t Octant::countChildren() const {
701 if (this->m_level < sm_treeConstants[m_dim].maxLevel){
702 return sm_treeConstants[m_dim].nChildren;
703 } else {
704 return 0;
705 }
706}
707
708// =================================================================================== //
709
713vector< Octant > Octant::buildChildren() const {
714
715 uint8_t nchildren = countChildren();
716 std::vector< Octant > children(nchildren);
717 buildChildren(children.data());
718
719 return children;
720}
721
722// =================================================================================== //
723
729void Octant::buildChildren(Octant *children) const {
730
731 u32array3 coords = getLogicalCoordinates();
732
733 int nChildren = countChildren();
734 for (int i=0; i<nChildren; ++i){
735 // Octant information
736 uint8_t xf;
737 uint8_t yf;
738 uint8_t zf;
739 uint8_t dx;
740 uint8_t dy;
741 uint8_t dz;
742 switch (i) {
743
744 case 0 :
745 dx = 0;
746 dy = 0;
747 dz = 0;
748
749 xf = 1;
750 yf = 3;
751 zf = 5;
752
753 break;
754
755 case 1 :
756 dx = 1;
757 dy = 0;
758 dz = 0;
759
760 xf = 0;
761 yf = 3;
762 zf = 5;
763
764 break;
765
766 case 2 :
767 dx = 0;
768 dy = 1;
769 dz = 0;
770
771 xf = 1;
772 yf = 2;
773 zf = 5;
774
775 break;
776
777 case 3 :
778 dx = 1;
779 dy = 1;
780 dz = 0;
781
782 xf = 0;
783 yf = 2;
784 zf = 5;
785
786 break;
787
788 case 4 :
789 dx = 0;
790 dy = 0;
791 dz = 1;
792
793 xf = 1;
794 yf = 3;
795 zf = 4;
796
797 break;
798
799 case 5 :
800 dx = 1;
801 dy = 0;
802 dz = 1;
803
804 xf = 0;
805 yf = 3;
806 zf = 4;
807
808 break;
809
810 case 6 :
811 dx = 0;
812 dy = 1;
813 dz = 1;
814
815 xf = 1;
816 yf = 2;
817 zf = 4;
818
819 break;
820
821 case 7 :
822 dx = 1;
823 dy = 1;
824 dz = 1;
825
826 xf = 0;
827 yf = 2;
828 zf = 4;
829
830 break;
831
832 default:
833 BITPIT_UNREACHABLE("The maximum number of children is 8.");
834
835 }
836
837 // Create octant
838 children[i] = Octant(*this);
839 Octant &oct = children[i];
840
841 oct.setMarker(std::max(0, oct.m_marker - 1));
842 oct.setLevel(oct.m_level + 1);
843
844 uint32_t dh = oct.getLogicalSize();
845 oct.m_morton = PABLO::computeMorton(m_dim, coords[0] + dh * dx, coords[1] + dh * dy, coords[2] + dh * dz);
846
847 oct.m_info[OctantInfo::INFO_NEW4REFINEMENT] = true;
848
849 oct.m_info[INFO_BOUNDFACE0 + xf] = false;
850 oct.m_info[INFO_BOUNDFACE0 + yf] = false;
851 oct.m_info[INFO_BOUNDFACE0 + zf] = false;
852
853 oct.m_info[INFO_PBOUNDFACE0 + xf] = false;
854 oct.m_info[INFO_PBOUNDFACE0 + yf] = false;
855 oct.m_info[INFO_PBOUNDFACE0 + zf] = false;
856 }
857};
858
864
865 u32array3 xx = getLogicalCoordinates();
866
867 //Delta to build father (use the boolean negation to identify the splitting node)
868 bool delta[3];
869 delta[2] = 0;
870 for (int i=0; i<m_dim; i++){
871 delta[i] = ((xx[i]%(uint32_t(1) << (sm_treeConstants[m_dim].maxLevel - max(0,(m_level-1))))) == 0);
872 }
873 return sm_treeConstants[m_dim].nodeFromCoordinates[delta[0]][delta[1]][delta[2]];
874};
875
876
877
878}
Octant class definition.
Definition Octant.hpp:89
bool getNodeBound(uint8_t node) const
Definition Octant.cpp:296
uint64_t computeNodePersistentKey(uint8_t inode) const
Definition Octant.cpp:635
int getGhostLayer() const
Definition Octant.cpp:373
void setPbound(uint8_t face, bool flag)
Definition Octant.cpp:410
u32array3 computeLastDescCoordinates() const
Definition Octant.cpp:597
uint8_t countChildren() const
Definition Octant.cpp:700
void getLogicalNode(u32array3 &node, uint8_t inode) const
Definition Octant.cpp:541
u32arr3vector getLogicalNodes() const
Definition Octant.cpp:531
u32array3 getLogicalCoordinates() const
Definition Octant.cpp:243
static unsigned int getBinarySize()
Definition Octant.cpp:658
uint32_t getDim() const
Definition Octant.cpp:237
void getNormal(uint8_t iface, i8array3 &normal, const int8_t(&normals)[6][3]) const
Definition Octant.cpp:569
bool getIsNewR() const
Definition Octant.cpp:355
Octant buildFather() const
Definition Octant.cpp:689
uint64_t getMorton() const
Definition Octant.cpp:580
void setMarker(int8_t marker)
Definition Octant.cpp:385
uint32_t getLogicalSize() const
Definition Octant.cpp:432
void setBalance(bool balance)
Definition Octant.cpp:393
uint64_t getLogicalArea() const
Definition Octant.cpp:440
darray3 getLogicalCenter() const
Definition Octant.cpp:458
std::vector< Octant > buildChildren() const
Definition Octant.cpp:713
uint8_t getLevel() const
Definition Octant.cpp:259
void setGhostLayer(int ghostLayer)
Definition Octant.cpp:419
darray3 getLogicalEdgeCenter(uint8_t iedge) const
Definition Octant.cpp:493
bool getIsNewC() const
Definition Octant.cpp:361
void setBound(uint8_t face)
Definition Octant.cpp:324
bool getEdgeBound(uint8_t edge) const
Definition Octant.cpp:281
darray3 getLogicalFaceCenter(uint8_t iface) const
Definition Octant.cpp:474
u32array3 computeFatherCoordinates() const
Definition Octant.cpp:619
int8_t getMarker() const
Definition Octant.cpp:265
bool getBound() const
Definition Octant.cpp:310
uint8_t getFamilySplittingNode() const
Definition Octant.cpp:863
void setLevel(uint8_t level)
Definition Octant.cpp:401
uint64_t computeFatherMorton() const
Definition Octant.cpp:609
Octant buildLastDesc() const
Definition Octant.cpp:678
bool getIsGhost() const
Definition Octant.cpp:367
uint64_t getLogicalVolume() const
Definition Octant.cpp:448
uint64_t computeLastDescMorton() const
Definition Octant.cpp:587
bool getPbound() const
Definition Octant.cpp:341
bool getBalance() const
Definition Octant.cpp:379
std::array< T, d > max(const std::array< T, d > &x, const std::array< T, d > &y)
#define BITPIT_UNREACHABLE(str)
Definition compiler.hpp:53
unsigned int check(std::ifstream &, std::vector< std::vector< int > > &)
Definition DGF.cpp:1169
Logger & operator<<(Logger &logger, LoggerManipulator< T > &&m)
Definition logger.hpp:367
static BITPIT_PUBLIC_API const Instances & instances()
--- layout: doxygen_footer ---