28#include "LocalTree.hpp"
32#include <unordered_map>
51 LocalTree::LocalTree() {
59 LocalTree::LocalTree(uint8_t dim){
76 LocalTree::getFirstDescMorton()
const{
77 return m_firstDescMorton;
84 LocalTree::getLastDescMorton()
const{
85 return m_lastDescMorton;
92 LocalTree::getNumGhosts()
const{
93 return m_ghosts.size();
100 LocalTree::getNumOctants()
const{
101 return m_octants.size();
109 LocalTree::getLocalMaxDepth()
const{
110 return m_localMaxDepth;
118 LocalTree::getMarker(int32_t idx)
const {
119 return m_octants[idx].getMarker();
127 LocalTree::getLevel(int32_t idx)
const {
128 return m_octants[idx].getLevel();
136 LocalTree::getMorton(int32_t idx)
const {
137 return m_octants[idx].getMorton();
147 LocalTree::computeNodePersistentKey(int32_t idx, uint8_t inode)
const {
148 return m_octants[idx].computeNodePersistentKey(inode);
156 LocalTree::getGhostLevel(int32_t idx)
const {
157 return m_ghosts[idx].getLevel();
165 LocalTree::computeGhostMorton(int32_t idx)
const {
166 return m_ghosts[idx].getMorton();
176 LocalTree::computeGhostNodePersistentKey(int32_t idx, uint8_t inode)
const {
177 return m_ghosts[idx].computeNodePersistentKey(inode);
185 LocalTree::getBalance(int32_t idx)
const{
186 return m_octants[idx].getBalance();
193 LocalTree::getBalanceCodim()
const{
194 return m_balanceCodim;
202 LocalTree::setMarker(int32_t idx, int8_t marker){
203 m_octants[idx].setMarker(marker);
211 LocalTree::setBalance(int32_t idx,
bool balance){
212 m_octants[idx].setBalance(balance);
219 LocalTree::setBalanceCodim(uint8_t b21codim){
220 m_balanceCodim = b21codim;
226 LocalTree::setFirstDescMorton(){
227 if(getNumOctants() > 0){
228 octvector::const_iterator firstOctant = m_octants.begin();
229 m_firstDescMorton = firstOctant->getMorton();
231 m_firstDescMorton = std::numeric_limits<uint64_t>::max();
238 LocalTree::setLastDescMorton(){
239 if(getNumOctants() > 0){
240 octvector::const_iterator lastOctant = m_octants.end() - 1;
241 uint32_t x,y,z,delta;
242 delta = (uint32_t)(1<<((uint8_t)m_treeConstants->
maxLevel - lastOctant->m_level)) - 1;
243 x = lastOctant->getLogicalCoordinates(0) + delta;
244 y = lastOctant->getLogicalCoordinates(1) + delta;
245 z = lastOctant->getLogicalCoordinates(2) + (m_dim-2)*delta;
246 Octant lastDesc = Octant(m_dim, m_treeConstants->
maxLevel,x,y,z);
247 m_lastDescMorton = lastDesc.getMorton();
249 m_lastDescMorton = 0;
257 LocalTree::setPeriodic(bvector & periodic){
258 m_periodic = periodic;
272 LocalTree::isPeriodic(
const Octant* oct, uint8_t iface)
const{
274 if (!oct->getBound(iface)) {
279 return m_periodic[iface];
289 LocalTree::isEdgePeriodic(
const Octant* oct, uint8_t iedge)
const{
291 if (!oct->getEdgeBound(iedge)) {
297 for (
int face : m_treeConstants->edgeFace[iedge]) {
298 if (oct->getBound(face) && !isPeriodic(oct, face)) {
314 LocalTree::isNodePeriodic(
const Octant* oct, uint8_t inode)
const{
316 if (!oct->getNodeBound(inode)) {
322 for (
int face : m_treeConstants->nodeFace[inode]) {
323 if (oct->getBound(face) && !isPeriodic(oct, face)) {
339 LocalTree::initialize() {
347 LocalTree::initialize(uint8_t dim) {
351 m_periodic.resize(m_dim*2);
356 m_treeConstants =
nullptr;
363 LocalTree::reset(
bool createRoot){
366 m_globalIdxGhosts.clear();
368 m_lastGhostBros.clear();
369 m_firstGhostBros.clear();
374 std::fill(m_periodic.begin(), m_periodic.end(),
false);
376 if (m_dim > 0 && createRoot) {
379 m_octants.push_back(Octant(m_dim));
381 m_localMaxDepth = -1;
384 setFirstDescMorton();
394 LocalTree::extractOctant(uint32_t idx){
395 return m_octants[idx];
403 LocalTree::extractOctant(uint32_t idx)
const{
404 return m_octants[idx];
412 LocalTree::extractGhostOctant(uint32_t idx) {
413 return m_ghosts[idx];
421 LocalTree::extractGhostOctant(uint32_t idx)
const{
422 return m_ghosts[idx];
438 LocalTree::refine(u32vector & mapidx){
440 uint32_t nOctants = m_octants.size();
449 uint32_t firstRefinedIdx = 0;
450 uint32_t nValidRefinements = 0;
451 for (uint32_t idx=0; idx<nOctants; idx++) {
453 Octant &octant = m_octants[idx];
454 if(octant.getMarker()<= 0){
459 if(octant.getLevel()>=m_treeConstants->
maxLevel){
466 if (nValidRefinements == 1) {
467 firstRefinedIdx = idx;
472 if (nValidRefinements == 0) {
479 uint32_t nFutureOctants = nOctants + (m_treeConstants->
nChildren - 1) * nValidRefinements;
481 m_octants.reserve(nFutureOctants);
482 m_octants.resize(nFutureOctants, Octant(m_dim));
483 m_octants.shrink_to_fit();
487 mapidx.resize(nFutureOctants);
498 bool refinementCompleted =
true;
500 uint32_t futureIdx = nFutureOctants - 1;
501 for (uint32_t n=0; n<(nOctants - firstRefinedIdx); ++n) {
502 uint32_t idx = nOctants - n - 1;
503 Octant &octant = m_octants[idx];
504 if(octant.getMarker()<=0){
507 if (futureIdx != idx) {
508 m_octants[futureIdx] = std::move(octant);
513 mapidx[futureIdx] = mapidx[idx];
520 Octant fatherOctant = std::move(octant);
523 uint8_t nChildren = fatherOctant.countChildren();
524 uint32_t firstChildIdx = futureIdx - (nChildren - 1);
525 fatherOctant.buildChildren(m_octants.data() + firstChildIdx);
529 for (uint8_t i=0; i<nChildren; i++){
530 mapidx[firstChildIdx + i] = mapidx[idx];
535 if (refinementCompleted) {
536 refinementCompleted = (m_octants[firstChildIdx].getMarker() <= 0);
540 uint8_t childrenLevel = m_octants[firstChildIdx].getLevel();
541 if (childrenLevel > m_localMaxDepth){
542 m_localMaxDepth = childrenLevel;
546 futureIdx -= nChildren;
550 return (!refinementCompleted);
561 LocalTree::coarse(u32vector & mapidx){
564 Octant father(m_dim);
570 uint32_t mapsize = mapidx.size();
571 int8_t markerfather, marker;
572 uint8_t nbro, nend, nstart;
573 uint8_t nchm1 = m_treeConstants->
nChildren-1;
574 bool docoarse =
false;
580 uint32_t nInitialOctants = getNumOctants();
581 if (nInitialOctants == 0) {
585 uint32_t nInitialGhosts = getNumGhosts();
587 nbro = nend = nstart = 0;
591 idx1_gh = nInitialGhosts - 1;
596 if (m_ghosts.size()){
599 check = idx1_gh < nInitialGhosts;
601 check = m_ghosts[idx1_gh].getMorton() > m_firstDescMorton;
603 if (check) idx1_gh--;
608 check = idx2_gh < nInitialGhosts;
610 check = m_ghosts[idx2_gh].getMorton() < m_lastDescMorton;
612 if (check) idx2_gh++;
617 for (idx=0; idx<nInitialOctants; idx++){
618 if(m_octants[idx].getMarker() < 0 && m_octants[idx].getLevel() > 0){
620 father = m_octants[idx].buildFather();
622 for (idx2=idx; idx2<idx+m_treeConstants->
nChildren; idx2++){
623 if (idx2<nInitialOctants){
624 if(m_octants[idx2].getMarker() < 0 && m_octants[idx2].buildFather() == father){
631 first_child_index.push_back(idx);
636 uint32_t nblock = nInitialOctants;
637 uint32_t nfchild = first_child_index.size();
639 nblock = nInitialOctants - nidx*nchm1;
641 for (idx=0; idx<nblock; idx++){
642 if (idx+offset < nInitialOctants){
644 if (idx+offset == first_child_index[nidx]){
645 markerfather = -m_treeConstants->
maxLevel;
646 father = m_octants[idx+offset].buildFather();
647 for (uint32_t iii=0; iii<Octant::INFO_ITEM_COUNT; iii++){
648 father.m_info[iii] =
false;
650 father.setGhostLayer(-1);
651 for(idx2=0; idx2<m_treeConstants->
nChildren; idx2++){
652 if (idx2 < nInitialOctants){
653 if (markerfather < m_octants[idx+offset+idx2].getMarker()+1){
654 markerfather = m_octants[idx+offset+idx2].getMarker()+1;
656 for (uint32_t iii=0; iii<Octant::INFO_ITEM_COUNT; iii++){
657 father.m_info[iii] = father.m_info[iii] || m_octants[idx+offset+idx2].m_info[iii];
661 father.m_info[Octant::INFO_NEW4COARSENING] =
true;
662 father.setMarker(markerfather);
667 m_octants[idx] = father;
668 if(mapsize > 0) mapidx[idx] = mapidx[idx+offset];
673 m_octants[idx] = m_octants[idx+offset];
674 if(mapsize > 0) mapidx[idx] = mapidx[idx+offset];
678 m_octants[idx] = m_octants[idx+offset];
679 if(mapsize > 0) mapidx[idx] = mapidx[idx+offset];
684 m_octants.resize(nblock, Octant(m_dim));
685 m_octants.shrink_to_fit();
686 nInitialOctants = m_octants.size();
688 mapidx.resize(nInitialOctants);
692 if (m_ghosts.size()){
694 if (nInitialOctants > 0 && idx1_gh < nInitialGhosts){
695 if (m_ghosts[idx1_gh].buildFather() == m_octants[0].buildFather()){
696 father = m_ghosts[idx1_gh].buildFather();
699 marker = m_ghosts[idx].getMarker();
700 bool waszero = (idx == 0);
701 while(marker < 0 && m_ghosts[idx].buildFather() == father){
710 marker = m_ghosts[idx].getMarker();
714 marker = m_octants[idx].getMarker();
715 if (idx==nInitialOctants-1) wstop =
true;
716 while(marker < 0 && m_octants[idx].buildFather() == father){
723 if (idx==nInitialOctants-1){
726 marker = m_octants[idx].getMarker();
736 for (idx=0; idx<nInitialOctants; idx++){
737 if (idx+offset < nInitialOctants){
738 m_octants[idx] = m_octants[idx+offset];
739 if(mapsize > 0) mapidx[idx] = mapidx[idx+offset];
742 m_octants.resize(nInitialOctants-offset, Octant(m_dim));
743 m_octants.shrink_to_fit();
744 nInitialOctants = m_octants.size();
746 mapidx.resize(nInitialOctants);
753 if (nInitialOctants > 0 && idx2_gh < nInitialGhosts){
755 if (m_ghosts[idx2_gh].buildFather() == father){
757 if (m_ghosts[idx2_gh].buildFather() == m_octants[nInitialOctants-1].buildFather()){
759 uint64_t idx22_gh = idx2_gh;
760 marker = m_ghosts[idx22_gh].getMarker();
761 while(marker < 0 && m_ghosts[idx22_gh].buildFather() == father){
764 if(idx22_gh == nInitialGhosts){
767 marker = m_ghosts[idx22_gh].getMarker();
785 if (nInitialOctants > 0 && idx2_gh < nInitialGhosts){
786 if (m_ghosts[idx2_gh].buildFather() == m_octants[nInitialOctants-1].buildFather()){
787 father = m_ghosts[idx2_gh].buildFather();
788 for (uint32_t iii=0; iii<Octant::INFO_ITEM_COUNT; iii++){
789 father.m_info[iii] =
false;
791 father.setGhostLayer(-1);
792 markerfather = m_ghosts[idx2_gh].getMarker()+1;
795 marker = m_ghosts[idx].getMarker();
796 while(marker < 0 && m_ghosts[idx].buildFather() == father){
798 if (markerfather < m_ghosts[idx].getMarker()+1){
799 markerfather = m_ghosts[idx].getMarker()+1;
801 for (uint32_t iii=0; iii<m_treeConstants->
nFaces; iii++){
802 father.m_info[iii] = father.m_info[iii] || m_ghosts[idx].m_info[iii];
804 father.m_info[Octant::INFO_BALANCED] = father.m_info[Octant::INFO_BALANCED] || m_ghosts[idx].m_info[Octant::INFO_BALANCED];
806 if(idx == nInitialGhosts){
809 marker = m_ghosts[idx].getMarker();
812 idx = nInitialOctants-1;
813 marker = m_octants[idx].getMarker();
814 if (idx==0) wstop =
true;
815 while(marker < 0 && m_octants[idx].buildFather() == father){
818 if (markerfather < m_octants[idx].getMarker()+1){
819 markerfather = m_octants[idx].getMarker()+1;
828 marker = m_octants[idx].getMarker();
838 for (idx=0; idx < nend; idx++){
839 for (uint32_t iii=0; iii<Octant::INFO_ITEM_COUNT - 1; iii++){
840 father.m_info[iii] = father.m_info[iii] || m_octants[nInitialOctants-idx-1].m_info[iii];
843 father.m_info[Octant::INFO_NEW4COARSENING] =
true;
844 father.setGhostLayer(-1);
849 father.setMarker(markerfather);
850 m_octants.resize(nInitialOctants-offset, Octant(m_dim));
851 m_octants.push_back(father);
852 m_octants.shrink_to_fit();
853 nInitialOctants = m_octants.size();
855 mapidx.resize(nInitialOctants);
863 updateLocalMaxDepth();
866 setFirstDescMorton();
880 LocalTree::globalRefine(u32vector & mapidx){
882 for (Octant &octant : m_octants){
886 return refine(mapidx);
897 LocalTree::globalCoarse(u32vector & mapidx){
899 for (Octant &octant : m_octants){
900 octant.setMarker(-1);
902 for (Octant &octant : m_ghosts){
903 octant.setMarker(-1);
906 return coarse(mapidx);
916 LocalTree::checkCoarse(uint64_t partLastDesc, u32vector & mapidx){
919 uint32_t mapsize = mapidx.size();
920 uint8_t toDelete = 0;
922 uint32_t nInitialOctants = getNumOctants();
923 if (nInitialOctants>0){
926 if (m_octants[idx].getMorton() < partLastDesc){
928 Octant father0 = m_octants[idx].buildFather();
929 Octant father = father0;
931 while(father == father0 && idx < nInitialOctants){
934 if (idx<nInitialOctants) father = m_octants[idx].buildFather();
937 if (nInitialOctants>toDelete){
938 for(idx=0; idx<nInitialOctants-toDelete; idx++){
939 m_octants[idx] = m_octants[idx+toDelete];
940 if (mapsize>0) mapidx[idx] = mapidx[idx+toDelete];
942 m_octants.resize(nInitialOctants-toDelete, Octant(m_dim));
944 mapidx.resize(m_octants.size());
951 setFirstDescMorton();
961 LocalTree::updateLocalMaxDepth(){
963 uint32_t noctants = getNumOctants();
967 for(i = 0; i < noctants; i++){
968 if(m_octants[i].getLevel() > m_localMaxDepth){
969 m_localMaxDepth = m_octants[i].getLevel();
987 LocalTree::findNeighbours(
const Octant* oct, uint8_t iface, u32vector & neighbours, bvector & isghost,
bool onlyinternal,
bool append)
const{
995 if (iface >= m_treeConstants->
nFaces){
1000 bool isperiodic =
false;
1001 if (oct->getBound(iface)) {
1002 isperiodic = isPeriodic(oct, iface);
1009 uint8_t level = oct->getLevel();
1013 neighbours.push_back(0);
1014 isghost.push_back(
false);
1020 uint32_t candidateIdx = 0;
1021 uint64_t candidateMorton = 0;
1023 uint64_t neighArea = 0;
1024 uint64_t faceArea = oct->getLogicalArea();
1026 uint32_t size = oct->getLogicalSize();
1028 std::array<uint32_t, 3> coord = oct->getLogicalCoordinates();
1031 coord[0] =
static_cast<uint32_t
>(coord[0] + periodicOffset[0]);
1032 coord[1] =
static_cast<uint32_t
>(coord[1] + periodicOffset[1]);
1033 coord[2] =
static_cast<uint32_t
>(coord[2] + periodicOffset[2]);
1036 const int8_t (&cxyz)[3] = m_treeConstants->
normals[iface];
1040 std::array<uint32_t, 3> sameSizeVirtualNeighCoord = coord;
1041 sameSizeVirtualNeighCoord[0] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[0] + sameSizeVirtualNeighOffset[0]);
1042 sameSizeVirtualNeighCoord[1] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[1] + sameSizeVirtualNeighOffset[1]);
1043 sameSizeVirtualNeighCoord[2] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[2] + sameSizeVirtualNeighOffset[2]);
1044 uint64_t sameSizeVirtualNeighMorton = PABLO::computeMorton(m_dim, sameSizeVirtualNeighCoord[0], sameSizeVirtualNeighCoord[1], sameSizeVirtualNeighCoord[2]);
1051 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_octants, &candidateIdx, &candidateMorton);
1054 if(candidateMorton == sameSizeVirtualNeighMorton && m_octants[candidateIdx].m_level == level){
1055 neighbours.push_back(candidateIdx);
1056 isghost.push_back(
false);
1066 std::array<uint32_t, 3> lastCandidateCoord = coord;
1067 lastCandidateCoord[0] =
static_cast<uint32_t
>(lastCandidateCoord[0] + lastCandidateOffset[0]);
1068 lastCandidateCoord[1] =
static_cast<uint32_t
>(lastCandidateCoord[1] + lastCandidateOffset[1]);
1069 lastCandidateCoord[2] =
static_cast<uint32_t
>(lastCandidateCoord[2] + lastCandidateOffset[2]);
1070 uint64_t lastCandidateMorton = PABLO::computeMorton(m_dim, lastCandidateCoord[0], lastCandidateCoord[1], lastCandidateCoord[2]);
1073 if (candidateIdx < getNumOctants()){
1076 u32array3 coordtry = {{0, 0, 0}};
1077 bool isNeighbourCandidate =
true;
1078 for (int8_t idim=0; idim<m_dim; idim++){
1079 coordtry[idim] = m_octants[candidateIdx].getLogicalCoordinates(idim);
1081 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(coordtry[idim] - coord[idim]));
1082 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_octants[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1084 isNeighbourCandidate =
false;
1089 if (isNeighbourCandidate){
1090 bool isNeighbour =
false;
1091 uint8_t leveltry = m_octants[candidateIdx].getLevel();
1092 if (leveltry > level){
1093 array<int64_t,3> coord1 ={{1, 1, 1}} ;
1094 for (int8_t idim=0; idim<m_dim; idim++){
1095 coord1[idim] = coord[idim] + size;
1098 if((
abs(cxyz[0])*((coordtry[1]>=coord[1])*(coordtry[1]<coord1[1]))*((coordtry[2]>=coord[2])*(coordtry[2]<coord1[2]))) + (
abs(cxyz[1])*((coordtry[0]>=coord[0])*(coordtry[0]<coord1[0]))*((coordtry[2]>=coord[2])*(coordtry[2]<coord1[2]))) + (
abs(cxyz[2])*((coordtry[0]>=coord[0])*(coordtry[0]<coord1[0]))*((coordtry[1]>=coord[1])*(coordtry[1]<coord1[1])))){
1102 else if (leveltry < level){
1103 u32array3 coordtry1 = {{1, 1, 1}};
1104 for (int8_t idim=0; idim<m_dim; idim++){
1105 coordtry1[idim] = coordtry[idim] + m_octants[candidateIdx].getLogicalSize();
1108 if((
abs(cxyz[0])*((coord[1]>=coordtry[1])*(coord[1]<coordtry1[1]))*((coord[2]>=coordtry[2])*(coord[2]<coordtry1[2]))) + (
abs(cxyz[1])*((coord[0]>=coordtry[0])*(coord[0]<coordtry1[0]))*((coord[2]>=coordtry[2])*(coord[2]<coordtry1[2]))) + (
abs(cxyz[2])*((coord[0]>=coordtry[0])*(coord[0]<coordtry1[0]))*((coord[1]>=coordtry[1])*(coord[1]<coordtry1[1])))){
1114 neighbours.push_back(candidateIdx);
1115 isghost.push_back(
false);
1119 neighArea += m_octants[candidateIdx].getLogicalArea();
1120 if (neighArea == faceArea){
1128 if (candidateIdx > getNumOctants() - 1){
1132 candidateMorton = m_octants[candidateIdx].getMorton();
1133 if (candidateMorton > lastCandidateMorton){
1145 bool ghostSearch = !onlyinternal && (getNumGhosts() > 0);
1147 if (!oct->getIsGhost() && !oct->getPbound(iface)){
1148 ghostSearch =
false;
1155 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_ghosts, &candidateIdx, &candidateMorton);
1158 if(candidateMorton == sameSizeVirtualNeighMorton && m_ghosts[candidateIdx].getLevel() == level){
1159 neighbours.push_back(candidateIdx);
1160 isghost.push_back(
true);
1165 if (candidateIdx < getNumGhosts()){
1168 u32array3 coordtry = {{0, 0, 0}};
1169 bool isNeighbourCandidate =
true;
1170 for (int8_t idim=0; idim<m_dim; idim++){
1171 coordtry[idim] = m_ghosts[candidateIdx].getLogicalCoordinates(idim);
1173 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(coordtry[idim] - coord[idim]));
1174 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_ghosts[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1176 isNeighbourCandidate =
false;
1181 if (isNeighbourCandidate){
1182 bool isNeighbour =
false;
1183 uint8_t leveltry = m_ghosts[candidateIdx].getLevel();
1184 if (leveltry > level){
1185 array<int64_t, 3> coord1 = {{1, 1, 1}};
1186 for (int8_t idim=0; idim<m_dim; idim++){
1187 coord1[idim] = coord[idim] + size;
1190 if((
abs(cxyz[0])*((coordtry[1]>=coord[1])*(coordtry[1]<coord1[1]))*((coordtry[2]>=coord[2])*(coordtry[2]<coord1[2]))) + (
abs(cxyz[1])*((coordtry[0]>=coord[0])*(coordtry[0]<coord1[0]))*((coordtry[2]>=coord[2])*(coordtry[2]<coord1[2]))) + (
abs(cxyz[2])*((coordtry[0]>=coord[0])*(coordtry[0]<coord1[0]))*((coordtry[1]>=coord[1])*(coordtry[1]<coord1[1])))){
1194 else if (leveltry < level){
1195 u32array3 coordtry1 = {{1, 1, 1}};
1196 for (int8_t idim=0; idim<m_dim; idim++){
1197 coordtry1[idim] = coordtry[idim] + m_ghosts[candidateIdx].getLogicalSize();
1200 if((
abs(cxyz[0])*((coord[1]>=coordtry[1])*(coord[1]<coordtry1[1]))*((coord[2]>=coordtry[2])*(coord[2]<coordtry1[2]))) + (
abs(cxyz[1])*((coord[0]>=coordtry[0])*(coord[0]<coordtry1[0]))*((coord[2]>=coordtry[2])*(coord[2]<coordtry1[2]))) + (
abs(cxyz[2])*((coord[0]>=coordtry[0])*(coord[0]<coordtry1[0]))*((coord[1]>=coordtry[1])*(coord[1]<coordtry1[1])))){
1206 neighbours.push_back(candidateIdx);
1207 isghost.push_back(
true);
1211 neighArea += m_ghosts[candidateIdx].getLogicalArea();
1212 if (neighArea == faceArea){
1219 if (candidateIdx > getNumGhosts() - 1){
1223 candidateMorton = m_ghosts[candidateIdx].getMorton();
1224 if (candidateMorton > lastCandidateMorton){
1244 LocalTree::findEdgeNeighbours(
const Octant* oct, uint8_t iedge, u32vector & neighbours, bvector & isghost,
bool onlyinternal,
bool append)
const{
1252 if (iedge >= m_treeConstants->
nEdges){
1257 bool isperiodic =
false;
1258 if (oct->getEdgeBound(iedge)) {
1259 isperiodic = isEdgePeriodic(oct, iedge);
1266 uint8_t level = oct->getLevel();
1270 neighbours.push_back(0);
1271 isghost.push_back(
false);
1277 uint32_t candidateIdx = 0;
1278 uint64_t candidateMorton = 0;
1280 uint32_t neighSize = 0;
1281 uint32_t edgeSize = oct->getLogicalSize();
1283 uint32_t size = oct->getLogicalSize();
1285 std::array<uint32_t, 3> coord = oct->getLogicalCoordinates();
1288 coord[0] =
static_cast<uint32_t
>(coord[0] + periodicOffset[0]);
1289 coord[1] =
static_cast<uint32_t
>(coord[1] + periodicOffset[1]);
1290 coord[2] =
static_cast<uint32_t
>(coord[2] + periodicOffset[2]);
1293 const int8_t (&cxyz)[3] = m_treeConstants->
edgeCoeffs[iedge];
1297 std::array<uint32_t, 3> sameSizeVirtualNeighCoord = coord;
1298 sameSizeVirtualNeighCoord[0] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[0] + sameSizeVirtualNeighOffset[0]);
1299 sameSizeVirtualNeighCoord[1] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[1] + sameSizeVirtualNeighOffset[1]);
1300 sameSizeVirtualNeighCoord[2] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[2] + sameSizeVirtualNeighOffset[2]);
1301 uint64_t sameSizeVirtualNeighMorton = PABLO::computeMorton(m_dim, sameSizeVirtualNeighCoord[0], sameSizeVirtualNeighCoord[1], sameSizeVirtualNeighCoord[2]);
1308 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_octants, &candidateIdx, &candidateMorton);
1311 if(candidateMorton == sameSizeVirtualNeighMorton && m_octants[candidateIdx].m_level == level){
1312 isghost.push_back(
false);
1313 neighbours.push_back(candidateIdx);
1323 std::array<uint32_t, 3> lastCandidateCoord = coord;
1324 lastCandidateCoord[0] =
static_cast<uint32_t
>(lastCandidateCoord[0] + lastCandidateOffset[0]);
1325 lastCandidateCoord[1] =
static_cast<uint32_t
>(lastCandidateCoord[1] + lastCandidateOffset[1]);
1326 lastCandidateCoord[2] =
static_cast<uint32_t
>(lastCandidateCoord[2] + lastCandidateOffset[2]);
1327 uint64_t lastCandidateMorton = PABLO::computeMorton(m_dim, lastCandidateCoord[0], lastCandidateCoord[1], lastCandidateCoord[2]);
1330 if (candidateIdx < getNumOctants()) {
1333 u32array3 coordtry = {{0, 0, 0}};
1334 bool isNeighbourCandidate =
true;
1335 for (int8_t idim=0; idim<m_dim; idim++){
1336 coordtry[idim] = m_octants[candidateIdx].getLogicalCoordinates(idim);
1338 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(-int32_t(coord[idim]) + int32_t(coordtry[idim])));
1339 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_octants[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1342 isNeighbourCandidate =
false;
1347 if (isNeighbourCandidate){
1348 bool isNeighbour =
false;
1349 uint8_t leveltry = m_octants[candidateIdx].getLevel();
1350 if (leveltry > level){
1351 u32array3 coord1 = {{1, 1, 1}};
1352 for (int8_t idim=0; idim<m_dim; idim++){
1353 coord1[idim] = coord[idim] + size;
1356 if((
abs(cxyz[0])*
abs(cxyz[2])*((coordtry[1]>=coord[1])*(coordtry[1]<coord1[1]))) + (
abs(cxyz[1])*
abs(cxyz[2])*((coordtry[0]>=coord[0])*(coordtry[0]<coord1[0]))) + (
abs(cxyz[0])*
abs(cxyz[1])*((coordtry[2]>=coord[2])*(coordtry[2]<coord1[2])))){
1360 else if (leveltry < level){
1361 u32array3 coordtry1 = {{1, 1, 1}};
1362 for (int8_t idim=0; idim<m_dim; idim++){
1363 coordtry1[idim] = coordtry[idim] + m_octants[candidateIdx].getLogicalSize();
1366 if((
abs(cxyz[0])*
abs(cxyz[2])*((coord[1]>=coordtry[1])*(coord[1]<coordtry1[1]))) + (
abs(cxyz[1])*
abs(cxyz[2])*((coord[0]>=coordtry[0])*(coord[0]<coordtry1[0]))) + (
abs(cxyz[0])*
abs(cxyz[1])*((coord[2]>=coordtry[2])*(coord[2]<coordtry1[2])))){
1372 neighbours.push_back(candidateIdx);
1373 isghost.push_back(
false);
1377 neighSize += m_octants[candidateIdx].getLogicalSize();
1378 if (neighSize == edgeSize){
1386 if (candidateIdx > getNumOctants()-1){
1390 candidateMorton = m_octants[candidateIdx].getMorton();
1391 if (candidateMorton > lastCandidateMorton){
1400 if (getNumGhosts() > 0 && !onlyinternal){
1402 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_ghosts, &candidateIdx, &candidateMorton);
1405 if(candidateMorton == sameSizeVirtualNeighMorton && m_ghosts[candidateIdx].m_level == level){
1406 isghost.push_back(
true);
1407 neighbours.push_back(candidateIdx);
1412 if (candidateIdx < getNumGhosts()){
1415 u32array3 coordtry = {{0, 0, 0}};
1416 bool isNeighbourCandidate =
true;
1417 for (int8_t idim=0; idim<m_dim; idim++){
1418 coordtry[idim] = m_ghosts[candidateIdx].getLogicalCoordinates(idim);
1420 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(-int32_t(coord[idim]) + int32_t(coordtry[idim])));
1421 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_ghosts[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1424 isNeighbourCandidate =
false;
1429 if (isNeighbourCandidate){
1430 bool isNeighbour =
false;
1431 uint8_t leveltry = m_ghosts[candidateIdx].getLevel();
1432 if (leveltry > level){
1433 u32array3 coord1 = {{1, 1, 1}};
1434 for (int8_t idim=0; idim<m_dim; idim++){
1435 coord1[idim] = int32_t(coord[idim]) + size;
1438 if((
abs(cxyz[0])*
abs(cxyz[2])*((coordtry[1]>=coord[1])*(coordtry[1]<coord1[1]))) + (
abs(cxyz[1])*
abs(cxyz[2])*((coordtry[0]>=coord[0])*(coordtry[0]<coord1[0]))) + (
abs(cxyz[0])*
abs(cxyz[1])*((coordtry[2]>=coord[2])*(coordtry[2]<coord1[2])))){
1442 else if (leveltry < level){
1443 u32array3 coordtry1 = {{1, 1, 1}};
1444 for (int8_t idim=0; idim<m_dim; idim++){
1445 coordtry1[idim] = coordtry[idim] + m_ghosts[candidateIdx].getLogicalSize();
1448 if((
abs(cxyz[0])*
abs(cxyz[2])*((coord[1]>=coordtry[1])*(coord[1]<coordtry1[1]))) + (
abs(cxyz[1])*
abs(cxyz[2])*((coord[0]>=coordtry[0])*(coord[0]<coordtry1[0]))) + (
abs(cxyz[0])*
abs(cxyz[1])*((coord[2]>=coordtry[2])*(coord[2]<coordtry1[2])))){
1454 neighbours.push_back(candidateIdx);
1455 isghost.push_back(
true);
1459 neighSize += m_ghosts[candidateIdx].getLogicalSize();
1460 if (neighSize == edgeSize){
1468 if (candidateIdx > getNumGhosts()-1){
1472 candidateMorton = m_ghosts[candidateIdx].getMorton();
1473 if (candidateMorton > lastCandidateMorton){
1493 LocalTree::findNodeNeighbours(
const Octant* oct, uint8_t inode, u32vector & neighbours, bvector & isghost,
bool onlyinternal,
bool append)
const{
1501 if (inode >= m_treeConstants->
nNodes){
1506 bool isperiodic =
false;
1507 if (oct->getNodeBound(inode)) {
1508 isperiodic = isNodePeriodic(oct, inode);
1515 uint8_t level = oct->getLevel();
1519 neighbours.push_back(0);
1520 isghost.push_back(
false);
1526 uint32_t candidateIdx = 0;
1527 uint64_t candidateMorton = 0;
1529 uint32_t size = oct->getLogicalSize();
1531 std::array<uint32_t, 3> coord = oct->getLogicalCoordinates();
1534 coord[0] =
static_cast<uint32_t
>(coord[0] + periodicOffset[0]);
1535 coord[1] =
static_cast<uint32_t
>(coord[1] + periodicOffset[1]);
1536 coord[2] =
static_cast<uint32_t
>(coord[2] + periodicOffset[2]);
1539 const int8_t (&cxyz)[3] = m_treeConstants->
nodeCoeffs[inode];
1543 std::array<uint32_t, 3> sameSizeVirtualNeighCoord = coord;
1544 sameSizeVirtualNeighCoord[0] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[0] + sameSizeVirtualNeighOffset[0]);
1545 sameSizeVirtualNeighCoord[1] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[1] + sameSizeVirtualNeighOffset[1]);
1546 sameSizeVirtualNeighCoord[2] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[2] + sameSizeVirtualNeighOffset[2]);
1547 uint64_t sameSizeVirtualNeighMorton = PABLO::computeMorton(m_dim, sameSizeVirtualNeighCoord[0], sameSizeVirtualNeighCoord[1], sameSizeVirtualNeighCoord[2]);
1554 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_octants, &candidateIdx, &candidateMorton);
1557 if(candidateMorton == sameSizeVirtualNeighMorton && m_octants[candidateIdx].m_level == oct->m_level){
1558 isghost.push_back(
false);
1559 neighbours.push_back(candidateIdx);
1569 std::array<uint32_t, 3> lastCandidateCoord = coord;
1570 lastCandidateCoord[0] =
static_cast<uint32_t
>(lastCandidateCoord[0] + lastCandidateOffset[0]);
1571 lastCandidateCoord[1] =
static_cast<uint32_t
>(lastCandidateCoord[1] + lastCandidateOffset[1]);
1572 lastCandidateCoord[2] =
static_cast<uint32_t
>(lastCandidateCoord[2] + lastCandidateOffset[2]);
1573 uint64_t lastCandidateMorton = PABLO::computeMorton(m_dim, lastCandidateCoord[0], lastCandidateCoord[1], lastCandidateCoord[2]);
1576 if (candidateIdx < getNumOctants()) {
1579 u32array3 coordtry = {{0, 0, 0}};
1580 bool isNeighbour =
true;
1581 for (int8_t idim=0; idim<m_dim; idim++){
1582 coordtry[idim] = m_octants[candidateIdx].getLogicalCoordinates(idim);
1584 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(-int32_t(coord[idim]) + int32_t(coordtry[idim])));
1585 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_octants[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1588 isNeighbour =
false;
1595 neighbours.push_back(candidateIdx);
1596 isghost.push_back(
false);
1601 if (candidateIdx > getNumOctants()-1){
1605 candidateMorton = m_octants[candidateIdx].getMorton();
1606 if (candidateMorton > lastCandidateMorton){
1616 if (getNumGhosts() > 0 && !onlyinternal){
1618 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_ghosts, &candidateIdx, &candidateMorton);
1621 if(candidateMorton == sameSizeVirtualNeighMorton && m_ghosts[candidateIdx].m_level == oct->m_level){
1622 isghost.push_back(
true);
1623 neighbours.push_back(candidateIdx);
1628 if (candidateIdx < getNumGhosts()) {
1631 u32array3 coordtry = {{0, 0, 0}};
1632 bool isNeighbour =
true;
1633 for (int8_t idim=0; idim<m_dim; idim++){
1634 coordtry[idim] = m_ghosts[candidateIdx].getLogicalCoordinates(idim);
1636 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(-int32_t(coord[idim]) + int32_t(coordtry[idim])));
1637 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_ghosts[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1640 isNeighbour =
false;
1647 neighbours.push_back(candidateIdx);
1648 isghost.push_back(
true);
1653 if (candidateIdx > getNumGhosts()-1){
1657 candidateMorton = m_ghosts[candidateIdx].getMorton();
1658 if (candidateMorton > lastCandidateMorton){
1684 LocalTree::computeNeighSearchBegin(uint64_t sameSizeVirtualNeighMorton,
const octvector &octants, uint32_t *searchBeginIdx, uint64_t *searchBeginMorton)
const {
1687 if (octants.empty()) {
1688 *searchBeginIdx = 0;
1689 *searchBeginMorton = PABLO::INVALID_MORTON;
1697 uint32_t lowerBoundIdx;
1698 uint64_t lowerBoundMorton;
1699 findMortonLowerBound(sameSizeVirtualNeighMorton, octants, &lowerBoundIdx, &lowerBoundMorton);
1701 if (lowerBoundMorton == sameSizeVirtualNeighMorton || lowerBoundIdx == 0) {
1702 *searchBeginIdx = lowerBoundIdx;
1703 *searchBeginMorton = lowerBoundMorton;
1705 *searchBeginIdx = lowerBoundIdx - 1;
1706 *searchBeginMorton = octants[*searchBeginIdx].getMorton();
1721 LocalTree::fixBrokenFamiliesMarkers(std::vector<Octant *> *updatedOctants, std::vector<bool> *updatedGhostFlags){
1724 bool updated =
false;
1726 uint32_t nocts = m_octants.size();
1731 uint32_t nghosts = m_ghosts.size();
1736 uint32_t idx1_gh = 0;
1737 uint32_t idx2_gh = 0;
1738 uint32_t last_idx =nocts-1;
1741 Octant father(m_dim);
1744 m_lastGhostBros.clear();
1745 m_firstGhostBros.clear();
1748 bool checkend =
true;
1749 bool checkstart =
true;
1752 while(m_ghosts[idx2_gh].getMorton() <= m_lastDescMorton){
1754 if (idx2_gh > nghosts-1)
break;
1756 if (idx2_gh > nghosts-1) checkend =
false;
1758 while(m_ghosts[idx1_gh].getMorton() <= m_octants[0].getMorton()){
1760 if (idx1_gh > nghosts-1)
break;
1762 if (idx1_gh == 0) checkstart =
false;
1767 if (m_ghosts[idx1_gh].buildFather()==m_octants[0].buildFather()){
1768 father = m_ghosts[idx1_gh].buildFather();
1771 int8_t marker = m_ghosts[idx].getMarker();
1772 while(marker < 0 && m_ghosts[idx].buildFather() == father){
1775 m_firstGhostBros.push_back(idx);
1781 marker = m_ghosts[idx].getMarker();
1784 while(idx<nocts && m_octants[idx].buildFather() == father){
1785 if (m_octants[idx].getMarker()<0)
1791 if (nbro != m_treeConstants->
nChildren && idx!=nocts){
1792 for(uint32_t ii=0; ii<idx; ii++){
1793 Octant &octant = m_octants[ii];
1794 if (octant.getMarker()<0){
1795 octant.setMarker(0);
1796 if (updatedOctants) {
1797 updatedOctants->push_back(&octant);
1799 if (updatedGhostFlags) {
1800 updatedGhostFlags->push_back(
false);
1806 m_firstGhostBros.clear();
1812 bool checklocal =
false;
1813 if (m_ghosts[idx2_gh].buildFather()==m_octants[nocts-1].buildFather()){
1814 father = m_ghosts[idx2_gh].buildFather();
1820 int8_t marker = m_ghosts[idx].getMarker();
1821 while(marker < 0 && m_ghosts[idx].buildFather() == father){
1824 m_lastGhostBros.push_back(idx);
1831 marker = m_ghosts[idx].getMarker();
1835 while(m_octants[idx].buildFather() == father){
1836 if (m_octants[idx].getMarker()<0)
1844 if (nbro != m_treeConstants->
nChildren && idx!=nocts-1){
1845 for(uint32_t ii=idx+1; ii<nocts; ii++){
1846 Octant &octant = m_octants[ii];
1847 if (octant.getMarker()<0){
1848 octant.setMarker(0);
1849 if (updatedOctants) {
1850 updatedOctants->push_back(&octant);
1852 if (updatedGhostFlags) {
1853 updatedGhostFlags->push_back(
false);
1859 m_lastGhostBros.clear();
1866 father = m_octants[0].buildFather();
1867 uint64_t mortonld = father.computeLastDescMorton();
1869 for (idx=0; idx<m_treeConstants->
nChildren; idx++){
1872 if (m_octants[idx].getMorton() <= mortonld){
1878 if (nbro != m_treeConstants->
nChildren) {
1883 for (idx=idx0; idx<nocts; idx++){
1884 Octant &octant = m_octants[idx];
1885 if(octant.getMarker() < 0 && octant.getLevel() > 0){
1887 father = octant.buildFather();
1889 for (idx2=idx; idx2<idx+m_treeConstants->
nChildren; idx2++){
1891 if(m_octants[idx2].getMarker() < 0 && m_octants[idx2].buildFather() == father){
1896 if (nbro == m_treeConstants->
nChildren){
1901 octant.setMarker(0);
1902 if (updatedOctants) {
1903 updatedOctants->push_back(&octant);
1905 if (updatedGhostFlags) {
1906 updatedGhostFlags->push_back(
false);
1926 LocalTree::localBalance(
bool doNew,
bool checkInterior,
bool checkGhost){
1928 bool balanceEdges = ((m_balanceCodim>1) && (m_dim==3));
1929 bool balanceNodes = (m_balanceCodim==m_dim);
1931 std::vector<Octant *> processOctants;
1932 std::vector<bool> processGhostFlags;
1936 for (Octant &octant : m_octants){
1938 bool balanceOctant = octant.getBalance();
1939 if (balanceOctant) {
1941 balanceOctant = (octant.getMarker() != 0) || octant.getIsNewC() || octant.getIsNewR();
1943 balanceOctant = (octant.getMarker() != 0);
1947 if (!balanceOctant) {
1952 processOctants.push_back(&octant);
1953 processGhostFlags.push_back(
false);
1966 for (Octant &octant : m_ghosts){
1968 if (octant.getGhostLayer() > 0) {
1973 processOctants.push_back(&octant);
1974 processGhostFlags.push_back(
true);
1979 std::vector<uint32_t> neighs;
1980 std::vector<bool> neighGhostFlags;
1982 bool updated =
false;
1983 std::vector<Octant *> updatedProcessOctants;
1984 std::vector<bool> updatedProcessGhostFlags;
1985 while (!processOctants.empty()) {
1987 bool brokenFamilieisFixed = fixBrokenFamiliesMarkers(&processOctants, &processGhostFlags);
1988 if (brokenFamilieisFixed) {
1993 std::size_t processSize = processOctants.size();
1994 for (std::size_t n = 0; n < processSize; ++n) {
1995 Octant &octant = *(processOctants[n]);
1996 bool ghostFlag = processGhostFlags[n];
2000 neighGhostFlags.clear();
2002 for (
int iface=0; iface < m_treeConstants->
nFaces; iface++) {
2003 findNeighbours(&octant, iface, neighs, neighGhostFlags, ghostFlag,
true);
2007 for (
int inode=0; inode < m_treeConstants->
nNodes; inode++) {
2008 findNodeNeighbours(&octant, inode, neighs, neighGhostFlags, ghostFlag,
true);
2013 for (
int iedge=0; iedge < m_treeConstants->
nEdges; iedge++) {
2014 findEdgeNeighbours(&octant, iedge, neighs, neighGhostFlags, ghostFlag,
true);
2019 int8_t level = octant.getLevel();
2020 int8_t futureLevel = std::min(m_treeConstants->
maxLevel,
static_cast<int8_t
>(level + octant.getMarker()));
2022 std::size_t nNeighs = neighs.size();
2023 for(std::size_t i = 0; i < nNeighs; i++){
2024 bool neighGhostFlag = neighGhostFlags[i];
2025 Octant &neighOctant = (neighGhostFlag ? m_ghosts[neighs[i]]: m_octants[neighs[i]]);
2027 int8_t neighLevel = neighOctant.getLevel();
2028 int8_t neighFutureLevel = std::min(m_treeConstants->
maxLevel, int8_t(neighLevel + neighOctant.getMarker()));
2029 if(!ghostFlag && futureLevel < neighFutureLevel - 1) {
2030 futureLevel = neighFutureLevel - 1;
2031 octant.setMarker(futureLevel - level);
2032 updatedProcessOctants.push_back(&octant);
2033 updatedProcessGhostFlags.push_back(ghostFlag);
2036 else if(!neighGhostFlag && neighFutureLevel < futureLevel - 1) {
2037 neighOctant.setMarker((futureLevel - 1) - neighLevel);
2038 if (neighOctant.getBalance()) {
2039 updatedProcessOctants.push_back(&neighOctant);
2040 updatedProcessGhostFlags.push_back(neighGhostFlag);
2048 updatedProcessOctants.swap(processOctants);
2049 updatedProcessGhostFlags.swap(processGhostFlags);
2051 updatedProcessOctants.clear();
2052 updatedProcessGhostFlags.clear();
2071 const int8_t (&normalizedOffsets)[3] = m_treeConstants->
normals[iface];
2074 uint32_t size = m_treeConstants->
lengths[level];
2075 uint32_t neighSize = m_treeConstants->
lengths[neighLevel];
2078 std::array<int64_t, 3> neighOffsets;
2079 for (
int i = 0; i < 3; ++i) {
2080 neighOffsets[i] = normalizedOffsets[i];
2081 if (neighOffsets[i] > 0) {
2082 neighOffsets[i] *= size;
2084 neighOffsets[i] *= neighSize;
2088 return neighOffsets;
2102 uint32_t size = m_treeConstants->
lengths[level];
2103 uint32_t neighSize = m_treeConstants->
lengths[neighLevel];
2108 uint32_t delta = size - neighSize;
2112 neighOffsets[1] += delta;
2113 neighOffsets[2] += delta;
2118 neighOffsets[0] += delta;
2119 neighOffsets[2] += delta;
2124 neighOffsets[0] += delta;
2125 neighOffsets[1] += delta;
2129 return neighOffsets;
2143 uint32_t neighSize = m_treeConstants->
lengths[neighLevel];
2168 int nNeighsDirection1 = 1 << (neighLevel - level);
2169 int nNeighsDirection2 = (m_dim > 2) ? nNeighsDirection1 : 1;
2170 int nNeighs = nNeighsDirection1 * nNeighsDirection2;
2175 for (
int j = 0; j < nNeighsDirection2; ++j) {
2176 for (
int i = 0; i < nNeighsDirection1; ++i) {
2177 (*neighOffsets)[k][direction1] += i * neighSize;
2178 (*neighOffsets)[k][direction2] += j * neighSize;
2195 const int8_t (&normalizedOffsets)[3] = m_treeConstants->
nodeCoeffs[inode];
2198 uint32_t size = m_treeConstants->
lengths[level];
2199 uint32_t neighSize = m_treeConstants->
lengths[neighLevel];
2202 std::array<int64_t, 3> neighOffsets;
2203 for (
int i = 0; i < 3; ++i) {
2204 neighOffsets[i] = normalizedOffsets[i];
2205 if (neighOffsets[i] > 0) {
2206 neighOffsets[i] *= size;
2208 neighOffsets[i] *= neighSize;
2212 return neighOffsets;
2252 const int8_t (&normalizedOffsets)[3] = m_treeConstants->
edgeCoeffs[iedge];
2255 uint32_t size = m_treeConstants->
lengths[level];
2256 uint32_t neighSize = m_treeConstants->
lengths[neighLevel];
2259 std::array<int64_t, 3> neighOffsets;
2260 for (
int i = 0; i < 3; ++i) {
2261 neighOffsets[i] = normalizedOffsets[i];
2262 if (neighOffsets[i] > 0) {
2263 neighOffsets[i] *= size;
2265 neighOffsets[i] *= neighSize;
2269 return neighOffsets;
2283 uint32_t size = m_treeConstants->
lengths[level];
2284 uint32_t neighSize = m_treeConstants->
lengths[neighLevel];
2289 uint32_t offset = size - neighSize;
2295 neighOffsets[1] += offset;
2302 neighOffsets[0] += offset;
2309 neighOffsets[2] += offset;
2313 return neighOffsets;
2327 uint32_t neighSize = m_treeConstants->
lengths[neighLevel];
2352 int nNeighs = 1 << (neighLevel - level);
2354 for (
int i = 1; i < nNeighs; ++i) {
2355 (*neighOffsets)[i][direction] += i * neighSize;
2370 std::array<int64_t, 3> offset = {{0, 0, 0}};
2371 if (!isPeriodic(&octant, iface)) {
2375 int64_t maxLength = m_treeConstants->
lengths[0];
2376 const int8_t (&referenceOffset)[3] = m_treeConstants->
normals[iface];
2378 for (
int d = 0; d < m_dim; ++d) {
2379 offset[d] = - maxLength *
static_cast<int64_t
>(referenceOffset[d]);
2394 std::array<int64_t, 3> offset = {{0, 0, 0}};
2395 for (
int i = 0; i < m_dim; ++i) {
2396 uint8_t face = m_treeConstants->
nodeFace[inode][i];
2397 if (!isPeriodic(&octant, face)) {
2402 for (
int d = 0; d < m_dim; ++d) {
2403 offset[d] += faceOffset[d];
2419 std::array<int64_t, 3> offset = {{0, 0, 0}};
2420 for (uint8_t face : m_treeConstants->
edgeFace[iedge]) {
2421 if (!isPeriodic(&octant, face)) {
2426 for (
int d = 0; d < m_dim; ++d) {
2427 offset[d] += faceOffset[d];
2459 if (octant.
getBalance() && m_balanceCodim == m_dim) {
2474 if (octant.
getBalance() && m_balanceCodim > 1) {
2486 LocalTree::computeIntersections() {
2488 octvector::iterator it, obegin, oend;
2490 u32vector neighbours;
2491 vector<bool> isghost;
2494 uint8_t iface, iface2;
2496 m_intersections.clear();
2497 m_intersections.reserve(2*3*m_octants.size());
2502 obegin = m_ghosts.begin();
2503 oend = m_ghosts.end();
2504 for (it = obegin; it != oend; ++it){
2505 for (iface = 0; iface < m_dim; iface++){
2507 findNeighbours(m_ghosts.data() + idx, iface2, neighbours, isghost,
true,
false);
2508 nsize = neighbours.size();
2509 if (!(it->m_info[iface2])){
2511 for (i = 0; i < nsize; i++){
2512 intersection.m_dim = m_dim;
2513 intersection.m_finer = getGhostLevel(idx) >= getLevel((
int)neighbours[i]);
2514 intersection.m_out = intersection.m_finer;
2515 intersection.m_outisghost = intersection.m_finer;
2516 intersection.m_owners[0] = neighbours[i];
2517 intersection.m_owners[1] = idx;
2518 intersection.m_iface = m_treeConstants->
oppositeFace[iface2] - (getGhostLevel(idx) >= getLevel((
int)neighbours[i]));
2519 intersection.m_isnew =
false;
2520 intersection.m_isghost =
true;
2521 intersection.m_bound =
false;
2522 intersection.m_pbound =
true;
2523 m_intersections.push_back(intersection);
2528 for (i = 0; i < nsize; i++){
2529 intersection.m_dim = m_dim;
2530 intersection.m_finer = getGhostLevel(idx) >= getLevel((
int)neighbours[i]);
2531 intersection.m_out = intersection.m_finer;
2532 intersection.m_outisghost = intersection.m_finer;
2533 intersection.m_owners[0] = neighbours[i];
2534 intersection.m_owners[1] = idx;
2535 intersection.m_iface = m_treeConstants->
oppositeFace[iface2] - (getGhostLevel(idx) >= getLevel((
int)neighbours[i]));
2536 intersection.m_isnew =
false;
2537 intersection.m_isghost =
true;
2538 intersection.m_bound =
true;
2539 intersection.m_pbound =
true;
2540 m_intersections.push_back(intersection);
2549 obegin = m_octants.begin();
2550 oend = m_octants.end();
2551 for (it = obegin; it != oend; ++it){
2552 for (iface = 0; iface < m_dim; iface++){
2554 findNeighbours(m_octants.data() + idx, iface2, neighbours, isghost,
false,
false);
2555 nsize = neighbours.size();
2557 if (!(it->m_info[iface2])){
2559 for (i = 0; i < nsize; i++){
2561 intersection.m_dim = m_dim;
2562 intersection.m_owners[0] = idx;
2563 intersection.m_owners[1] = neighbours[i];
2564 intersection.m_finer = (nsize>1);
2565 intersection.m_out = (nsize>1);
2566 intersection.m_outisghost = (nsize>1);
2567 intersection.m_iface = iface2 + (nsize>1);
2568 intersection.m_isnew =
false;
2569 intersection.m_isghost =
true;
2570 intersection.m_bound =
false;
2571 intersection.m_pbound =
true;
2572 m_intersections.push_back(intersection);
2575 intersection.m_dim = m_dim;
2576 intersection.m_owners[0] = idx;
2577 intersection.m_owners[1] = neighbours[i];
2578 intersection.m_finer = (nsize>1);
2579 intersection.m_out = (nsize>1);
2580 intersection.m_outisghost =
false;
2581 intersection.m_iface = iface2 + (nsize>1);
2582 intersection.m_isnew =
false;
2583 intersection.m_isghost =
false;
2584 intersection.m_bound =
false;
2585 intersection.m_pbound =
false;
2586 m_intersections.push_back(intersection);
2592 for (i = 0; i < nsize; i++){
2594 intersection.m_dim = m_dim;
2595 intersection.m_owners[0] = idx;
2596 intersection.m_owners[1] = neighbours[i];
2597 intersection.m_finer = (nsize>1);
2598 intersection.m_out = intersection.m_finer;
2599 intersection.m_outisghost = intersection.m_finer;
2600 intersection.m_iface = iface2 + (nsize>1);
2601 intersection.m_isnew =
false;
2602 intersection.m_isghost =
true;
2603 intersection.m_bound =
true;
2604 intersection.m_pbound =
true;
2605 m_intersections.push_back(intersection);
2608 intersection.m_dim = m_dim;
2609 intersection.m_owners[0] = idx;
2610 intersection.m_owners[1] = neighbours[i];
2611 intersection.m_finer = (nsize>1);
2612 intersection.m_out = intersection.m_finer;
2613 intersection.m_outisghost =
false;
2614 intersection.m_iface = iface2 + (nsize>1);
2615 intersection.m_isnew =
false;
2616 intersection.m_isghost =
false;
2617 intersection.m_bound =
true;
2618 intersection.m_pbound =
false;
2619 m_intersections.push_back(intersection);
2626 intersection.m_dim = m_dim;
2627 intersection.m_owners[0] = idx;
2628 intersection.m_owners[1] = idx;
2629 intersection.m_finer = 0;
2630 intersection.m_out = 0;
2631 intersection.m_outisghost =
false;
2632 intersection.m_iface = iface2;
2633 intersection.m_isnew =
false;
2634 intersection.m_isghost =
false;
2635 intersection.m_bound =
true;
2636 intersection.m_pbound =
false;
2637 m_intersections.push_back(intersection);
2639 if (it->m_info[iface2+1]){
2640 if (!(m_periodic[iface2+1])){
2642 intersection.m_dim = m_dim;
2643 intersection.m_owners[0] = idx;
2644 intersection.m_owners[1] = idx;
2645 intersection.m_finer = 0;
2646 intersection.m_out = 0;
2647 intersection.m_outisghost =
false;
2648 intersection.m_iface = iface2+1;
2649 intersection.m_isnew =
false;
2650 intersection.m_isghost =
false;
2651 intersection.m_bound =
true;
2652 intersection.m_pbound =
false;
2653 m_intersections.push_back(intersection);
2657 findNeighbours(m_octants.data() + idx, iface2+1, neighbours, isghost,
false,
false);
2658 nsize = neighbours.size();
2659 for (i = 0; i < nsize; i++){
2661 intersection.m_dim = m_dim;
2662 intersection.m_owners[0] = idx;
2663 intersection.m_owners[1] = neighbours[i];
2664 intersection.m_finer = (nsize>1);
2665 intersection.m_out = intersection.m_finer;
2666 intersection.m_outisghost = intersection.m_finer;
2667 intersection.m_iface = iface2 + (nsize>1);
2668 intersection.m_isnew =
false;
2669 intersection.m_isghost =
true;
2670 intersection.m_bound =
true;
2671 intersection.m_pbound =
true;
2672 m_intersections.push_back(intersection);
2675 intersection.m_dim = m_dim;
2676 intersection.m_owners[0] = idx;
2677 intersection.m_owners[1] = neighbours[i];
2678 intersection.m_finer = (nsize>1);
2679 intersection.m_out = intersection.m_finer;
2680 intersection.m_outisghost =
false;
2681 intersection.m_iface = iface2 + (nsize>1);
2682 intersection.m_isnew =
false;
2683 intersection.m_isghost =
false;
2684 intersection.m_bound =
true;
2685 intersection.m_pbound =
false;
2686 m_intersections.push_back(intersection);
2694 intervector(m_intersections).swap(m_intersections);
2703 LocalTree::findMorton(uint64_t targetMorton)
const {
2704 return findMorton(targetMorton, m_octants);
2713 LocalTree::findGhostMorton(uint64_t targetMorton)
const {
2714 return findMorton(targetMorton, m_ghosts);
2727 LocalTree::findMorton(uint64_t targetMorton,
const octvector &octants)
const {
2729 uint32_t lowerBoundIdx;
2730 uint64_t lowerBoundMorton;
2731 findMortonLowerBound(targetMorton, octants, &lowerBoundIdx, &lowerBoundMorton);
2734 if (lowerBoundMorton == targetMorton) {
2735 targetIdx = lowerBoundIdx;
2737 targetIdx = octants.size();
2762 LocalTree::findMortonLowerBound(uint64_t targetMorton,
const octvector &octants, uint32_t *lowerBoundIdx, uint64_t *lowerBoundMorton)
const {
2764 uint32_t nOctants = octants.size();
2766 uint32_t lowIndex = 0;
2767 uint32_t highIndex = nOctants;
2768 uint32_t midIndex = nOctants;
2769 uint64_t midMorton = PABLO::INVALID_MORTON;
2770 while (lowIndex < highIndex) {
2771 midIndex = lowIndex + (highIndex - lowIndex) / 2;
2772 midMorton = octants[midIndex].getMorton();
2773 if (targetMorton < midMorton) {
2774 highIndex = midIndex;
2776 else if (targetMorton > midMorton) {
2777 lowIndex = midIndex + 1;
2780 *lowerBoundIdx = midIndex;
2781 *lowerBoundMorton = midMorton;
2787 *lowerBoundIdx = lowIndex;
2788 if (*lowerBoundIdx == midIndex) {
2789 *lowerBoundMorton = midMorton;
2791 else if (*lowerBoundIdx < nOctants) {
2792 *lowerBoundMorton = octants[*lowerBoundIdx].getMorton();
2795 *lowerBoundMorton = PABLO::INVALID_MORTON;
2817 LocalTree::findMortonUpperBound(uint64_t targetMorton,
const octvector &octants, uint32_t *upperBoundIdx, uint64_t *upperBoundMorton)
const {
2819 uint32_t nOctants = octants.size();
2821 uint32_t lowIndex = 0;
2822 uint32_t highIndex = nOctants;
2823 uint32_t midIndex = nOctants;
2824 uint64_t midMorton = PABLO::INVALID_MORTON;
2825 while (lowIndex < highIndex) {
2826 midIndex = lowIndex + (highIndex - lowIndex) / 2;
2827 midMorton = octants[midIndex].getMorton();
2828 if (targetMorton < midMorton) {
2829 highIndex = midIndex;
2832 lowIndex = midIndex + 1;
2836 *upperBoundIdx = lowIndex;
2837 if (*upperBoundIdx == midIndex) {
2838 *upperBoundMorton = midMorton;
2840 else if (*upperBoundIdx < nOctants) {
2841 *upperBoundMorton = octants[*upperBoundIdx].getMorton();
2844 *upperBoundMorton = PABLO::INVALID_MORTON;
2854 LocalTree::computeConnectivity(){
2855 vector<uint64_t> nodeKeys;
2856 unordered_map<uint64_t, array<uint32_t, 3> > nodeCoords;
2857 unordered_map<uint64_t, vector<uint64_t> > nodeOctants;
2858 uint32_t noctants = getNumOctants();
2859 uint32_t nghosts = getNumGhosts();
2864 nodeKeys.reserve(noctants);
2865 nodeCoords.reserve(noctants);
2866 nodeOctants.reserve(noctants);
2868 for (uint64_t n = 0; n < (noctants + nghosts); n++){
2869 const Octant *octant;
2871 uint32_t octantId =
static_cast<uint32_t
>(n);
2872 octant = &(m_octants[octantId]);
2874 uint32_t octantId =
static_cast<uint32_t
>(n - noctants);
2875 octant = &(m_ghosts[octantId]);
2878 for (uint8_t i = 0; i < m_treeConstants->
nNodes; ++i){
2880 octant->getLogicalNode(node, i);
2882 uint64_t nodeKey = octant->computeNodePersistentKey(node);
2883 if (nodeCoords.count(nodeKey) == 0) {
2884 nodeKeys.push_back(nodeKey);
2885 nodeCoords.insert({{nodeKey, std::move(node)}});
2886 nodeOctants[nodeKey].reserve(m_treeConstants->
nNodes);
2889 nodeOctants[nodeKey].push_back(n);
2892 std::sort(nodeKeys.begin(), nodeKeys.end());
2896 m_connectivity.clear();
2897 m_ghostsConnectivity.clear();
2899 m_nodes.reserve(nodeKeys.size());
2900 m_connectivity.resize(noctants);
2901 m_ghostsConnectivity.resize(nghosts);
2903 uint32_t nodeId = 0;
2904 for (uint64_t nodeKey : nodeKeys) {
2905 m_nodes.emplace_back(std::move(nodeCoords.at(nodeKey)));
2906 for (uint64_t n : nodeOctants.at(nodeKey)) {
2907 std::vector<uint32_t> *octantConnect;
2909 uint32_t octantId =
static_cast<uint32_t
>(n);
2910 octantConnect = &(m_connectivity[octantId]);
2912 uint32_t octantId =
static_cast<uint32_t
>(n - noctants);
2913 octantConnect = &(m_ghostsConnectivity[octantId]);
2916 if (octantConnect->size() == 0) {
2917 octantConnect->reserve(m_treeConstants->
nNodes);
2919 octantConnect->push_back(nodeId);
2924 m_nodes.shrink_to_fit();
2933 LocalTree::clearConnectivity(
bool release){
2936 u32vector2D().swap(m_connectivity);
2937 u32vector2D().swap(m_ghostsConnectivity);
2940 m_connectivity.clear();
2941 m_ghostsConnectivity.clear();
2948 LocalTree::updateConnectivity(){
2949 clearConnectivity(
false);
2950 computeConnectivity();
Intersection class definition.
void computeVirtualNodeNeighOffsets(uint8_t level, uint8_t inode, uint8_t neighLevel, std::vector< std::array< int64_t, 3 > > *neighOffsets) const
uint8_t getMaxEdgeNeighLevel(const Octant &octant) const
std::array< int64_t, 3 > computeLastVirtualEdgeNeighOffset(uint8_t level, uint8_t iedge, uint8_t neighLevel) const
std::vector< Intersection > intervector
uint8_t getMaxNeighLevel(const Octant &octant) const
uint8_t getMaxNodeNeighLevel(const Octant &octant) const
std::array< int64_t, 3 > getEdgePeriodicOffset(const Octant &octant, uint8_t iedge) const
std::array< int64_t, 3 > getPeriodicOffset(const Octant &octant, uint8_t iface) const
std::array< int64_t, 3 > computeLastVirtualNeighOffset(uint8_t level, uint8_t iface, uint8_t neighLevel) const
std::vector< uint32_t > u32vector
void computeVirtualEdgeNeighOffsets(uint8_t level, uint8_t iedge, uint8_t neighLevel, std::vector< std::array< int64_t, 3 > > *neighOffsets) const
std::vector< u32array3 > u32arr3vector
std::array< int64_t, 3 > computeLastVirtualNodeNeighOffset(uint8_t level, uint8_t inode, uint8_t neighLevel) const
std::array< int64_t, 3 > computeFirstVirtualNeighOffset(uint8_t level, uint8_t iface, uint8_t neighLevel) const
std::array< int64_t, 3 > computeFirstVirtualEdgeNeighOffset(uint8_t level, uint8_t iedge, uint8_t neighLevel) const
void computeVirtualNeighOffsets(uint8_t level, uint8_t iface, uint8_t neighLevel, std::vector< std::array< int64_t, 3 > > *neighOffsets) const
std::array< int64_t, 3 > computeFirstVirtualNodeNeighOffset(uint8_t level, uint8_t inode, uint8_t neighLevel) const
std::array< int64_t, 3 > getNodePeriodicOffset(const Octant &octant, uint8_t inode) const
std::array< T, d > abs(const std::array< T, d > &x)
unsigned int check(std::ifstream &, std::vector< std::vector< int > > &)
std::vector< uint32_t > lengths
static BITPIT_PUBLIC_API const TreeConstants & instance(uint8_t dim)