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);
528 for (
int i = 0; i < nChildren; ++i) {
529 m_octants[firstChildIdx + i].m_info[Octant::INFO_NEW4REFINEMENT] =
true;
534 for (uint8_t i=0; i<nChildren; i++){
535 mapidx[firstChildIdx + i] = mapidx[idx];
540 if (refinementCompleted) {
541 refinementCompleted = (m_octants[firstChildIdx].getMarker() <= 0);
545 uint8_t childrenLevel = m_octants[firstChildIdx].getLevel();
546 if (childrenLevel > m_localMaxDepth){
547 m_localMaxDepth = childrenLevel;
551 futureIdx -= nChildren;
555 return (!refinementCompleted);
566 LocalTree::coarse(u32vector & mapidx){
569 Octant father(m_dim);
575 uint32_t mapsize = mapidx.size();
576 int8_t markerfather, marker;
577 uint8_t nbro, nend, nstart;
578 uint8_t nchm1 = m_treeConstants->nChildren-1;
579 bool docoarse =
false;
585 uint32_t nInitialOctants = getNumOctants();
586 if (nInitialOctants == 0) {
590 uint32_t nInitialGhosts = getNumGhosts();
592 nbro = nend = nstart = 0;
596 idx1_gh = nInitialGhosts - 1;
601 if (m_ghosts.size()){
604 check = idx1_gh < nInitialGhosts;
606 check = m_ghosts[idx1_gh].getMorton() > m_firstDescMorton;
608 if (check) idx1_gh--;
613 check = idx2_gh < nInitialGhosts;
615 check = m_ghosts[idx2_gh].getMorton() < m_lastDescMorton;
617 if (check) idx2_gh++;
622 for (idx=0; idx<nInitialOctants; idx++){
623 if(m_octants[idx].getMarker() < 0 && m_octants[idx].getLevel() > 0){
625 father = m_octants[idx].buildFather();
627 for (idx2=idx; idx2<idx+m_treeConstants->nChildren; idx2++){
628 if (idx2<nInitialOctants){
629 if(m_octants[idx2].getMarker() < 0 && m_octants[idx2].buildFather() == father){
634 if (nbro == m_treeConstants->nChildren){
636 first_child_index.push_back(idx);
641 uint32_t nblock = nInitialOctants;
642 uint32_t nfchild = first_child_index.size();
644 nblock = nInitialOctants - nidx*nchm1;
646 for (idx=0; idx<nblock; idx++){
647 if (idx+offset < nInitialOctants){
649 if (idx+offset == first_child_index[nidx]){
650 markerfather = -m_treeConstants->maxLevel;
651 father = m_octants[idx+offset].buildFather();
652 for (uint32_t iii=0; iii<Octant::INFO_ITEM_COUNT; iii++){
653 father.m_info[iii] =
false;
655 father.setGhostLayer(-1);
656 for(idx2=0; idx2<m_treeConstants->nChildren; idx2++){
657 if (idx2 < nInitialOctants){
658 if (markerfather < m_octants[idx+offset+idx2].getMarker()+1){
659 markerfather = m_octants[idx+offset+idx2].getMarker()+1;
661 for (uint32_t iii=0; iii<Octant::INFO_ITEM_COUNT; iii++){
662 father.m_info[iii] = father.m_info[iii] || m_octants[idx+offset+idx2].m_info[iii];
666 father.m_info[Octant::INFO_NEW4COARSENING] =
true;
667 father.setMarker(markerfather);
672 m_octants[idx] = father;
673 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];
683 m_octants[idx] = m_octants[idx+offset];
684 if(mapsize > 0) mapidx[idx] = mapidx[idx+offset];
689 m_octants.resize(nblock, Octant(m_dim));
690 m_octants.shrink_to_fit();
691 nInitialOctants = m_octants.size();
693 mapidx.resize(nInitialOctants);
697 if (m_ghosts.size()){
699 if (nInitialOctants > 0 && idx1_gh < nInitialGhosts){
700 if (m_ghosts[idx1_gh].buildFather() == m_octants[0].buildFather()){
701 father = m_ghosts[idx1_gh].buildFather();
704 marker = m_ghosts[idx].getMarker();
705 bool waszero = (idx == 0);
706 while(marker < 0 && m_ghosts[idx].buildFather() == father){
715 marker = m_ghosts[idx].getMarker();
719 marker = m_octants[idx].getMarker();
720 if (idx==nInitialOctants-1) wstop =
true;
721 while(marker < 0 && m_octants[idx].buildFather() == father){
728 if (idx==nInitialOctants-1){
731 marker = m_octants[idx].getMarker();
733 if (nbro == m_treeConstants->nChildren){
741 for (idx=0; idx<nInitialOctants; idx++){
742 if (idx+offset < nInitialOctants){
743 m_octants[idx] = m_octants[idx+offset];
744 if(mapsize > 0) mapidx[idx] = mapidx[idx+offset];
747 m_octants.resize(nInitialOctants-offset, Octant(m_dim));
748 m_octants.shrink_to_fit();
749 nInitialOctants = m_octants.size();
751 mapidx.resize(nInitialOctants);
758 if (nInitialOctants > 0 && idx2_gh < nInitialGhosts){
760 if (m_ghosts[idx2_gh].buildFather() == father){
762 if (m_ghosts[idx2_gh].buildFather() == m_octants[nInitialOctants-1].buildFather()){
764 uint64_t idx22_gh = idx2_gh;
765 marker = m_ghosts[idx22_gh].getMarker();
766 while(marker < 0 && m_ghosts[idx22_gh].buildFather() == father){
769 if(idx22_gh == nInitialGhosts){
772 marker = m_ghosts[idx22_gh].getMarker();
775 if (nbro == m_treeConstants->nChildren){
790 if (nInitialOctants > 0 && idx2_gh < nInitialGhosts){
791 if (m_ghosts[idx2_gh].buildFather() == m_octants[nInitialOctants-1].buildFather()){
792 father = m_ghosts[idx2_gh].buildFather();
793 for (uint32_t iii=0; iii<Octant::INFO_ITEM_COUNT; iii++){
794 father.m_info[iii] =
false;
796 father.setGhostLayer(-1);
797 markerfather = m_ghosts[idx2_gh].getMarker()+1;
800 marker = m_ghosts[idx].getMarker();
801 while(marker < 0 && m_ghosts[idx].buildFather() == father){
803 if (markerfather < m_ghosts[idx].getMarker()+1){
804 markerfather = m_ghosts[idx].getMarker()+1;
806 for (uint32_t iii=0; iii<m_treeConstants->nFaces; iii++){
807 father.m_info[iii] = father.m_info[iii] || m_ghosts[idx].m_info[iii];
809 father.m_info[Octant::INFO_BALANCED] = father.m_info[Octant::INFO_BALANCED] || m_ghosts[idx].m_info[Octant::INFO_BALANCED];
811 if(idx == nInitialGhosts){
814 marker = m_ghosts[idx].getMarker();
817 idx = nInitialOctants-1;
818 marker = m_octants[idx].getMarker();
819 if (idx==0) wstop =
true;
820 while(marker < 0 && m_octants[idx].buildFather() == father){
823 if (markerfather < m_octants[idx].getMarker()+1){
824 markerfather = m_octants[idx].getMarker()+1;
833 marker = m_octants[idx].getMarker();
835 if (nbro == m_treeConstants->nChildren){
843 for (idx=0; idx < nend; idx++){
844 for (uint32_t iii=0; iii<Octant::INFO_ITEM_COUNT - 1; iii++){
845 father.m_info[iii] = father.m_info[iii] || m_octants[nInitialOctants-idx-1].m_info[iii];
848 father.m_info[Octant::INFO_NEW4COARSENING] =
true;
849 father.setGhostLayer(-1);
854 father.setMarker(markerfather);
855 m_octants.resize(nInitialOctants-offset, Octant(m_dim));
856 m_octants.push_back(father);
857 m_octants.shrink_to_fit();
858 nInitialOctants = m_octants.size();
860 mapidx.resize(nInitialOctants);
868 updateLocalMaxDepth();
871 setFirstDescMorton();
885 LocalTree::globalRefine(u32vector & mapidx){
887 for (Octant &octant : m_octants){
891 return refine(mapidx);
902 LocalTree::globalCoarse(u32vector & mapidx){
904 for (Octant &octant : m_octants){
905 octant.setMarker(-1);
907 for (Octant &octant : m_ghosts){
908 octant.setMarker(-1);
911 return coarse(mapidx);
921 LocalTree::checkCoarse(uint64_t partLastDesc, u32vector & mapidx){
924 uint32_t mapsize = mapidx.size();
925 uint8_t toDelete = 0;
927 uint32_t nInitialOctants = getNumOctants();
928 if (nInitialOctants>0){
931 if (m_octants[idx].getMorton() < partLastDesc){
933 Octant father0 = m_octants[idx].buildFather();
934 Octant father = father0;
936 while(father == father0 && idx < nInitialOctants){
939 if (idx<nInitialOctants) father = m_octants[idx].buildFather();
942 if (nInitialOctants>toDelete){
943 for(idx=0; idx<nInitialOctants-toDelete; idx++){
944 m_octants[idx] = m_octants[idx+toDelete];
945 if (mapsize>0) mapidx[idx] = mapidx[idx+toDelete];
947 m_octants.resize(nInitialOctants-toDelete, Octant(m_dim));
949 mapidx.resize(m_octants.size());
956 setFirstDescMorton();
966 LocalTree::updateLocalMaxDepth(){
968 uint32_t noctants = getNumOctants();
972 for(i = 0; i < noctants; i++){
973 if(m_octants[i].getLevel() > m_localMaxDepth){
974 m_localMaxDepth = m_octants[i].getLevel();
992 LocalTree::findNeighbours(
const Octant* oct, uint8_t iface, u32vector & neighbours, bvector & isghost,
bool onlyinternal,
bool append)
const{
1000 if (iface >= m_treeConstants->nFaces){
1005 bool isperiodic =
false;
1006 if (oct->getBound(iface)) {
1007 isperiodic = isPeriodic(oct, iface);
1014 uint8_t level = oct->getLevel();
1018 neighbours.push_back(0);
1019 isghost.push_back(
false);
1025 uint32_t candidateIdx = 0;
1026 uint64_t candidateMorton = 0;
1028 uint64_t neighArea = 0;
1029 uint64_t faceArea = oct->getLogicalArea();
1031 uint32_t size = oct->getLogicalSize();
1033 std::array<uint32_t, 3> coord = oct->getLogicalCoordinates();
1036 coord[0] =
static_cast<uint32_t
>(coord[0] + periodicOffset[0]);
1037 coord[1] =
static_cast<uint32_t
>(coord[1] + periodicOffset[1]);
1038 coord[2] =
static_cast<uint32_t
>(coord[2] + periodicOffset[2]);
1041 const int8_t (&cxyz)[3] = m_treeConstants->normals[iface];
1045 std::array<uint32_t, 3> sameSizeVirtualNeighCoord = coord;
1046 sameSizeVirtualNeighCoord[0] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[0] + sameSizeVirtualNeighOffset[0]);
1047 sameSizeVirtualNeighCoord[1] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[1] + sameSizeVirtualNeighOffset[1]);
1048 sameSizeVirtualNeighCoord[2] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[2] + sameSizeVirtualNeighOffset[2]);
1049 uint64_t sameSizeVirtualNeighMorton = PABLO::computeMorton(m_dim, sameSizeVirtualNeighCoord[0], sameSizeVirtualNeighCoord[1], sameSizeVirtualNeighCoord[2]);
1056 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_octants, &candidateIdx, &candidateMorton);
1059 if(candidateMorton == sameSizeVirtualNeighMorton && m_octants[candidateIdx].m_level == level){
1060 neighbours.push_back(candidateIdx);
1061 isghost.push_back(
false);
1071 std::array<uint32_t, 3> lastCandidateCoord = coord;
1072 lastCandidateCoord[0] =
static_cast<uint32_t
>(lastCandidateCoord[0] + lastCandidateOffset[0]);
1073 lastCandidateCoord[1] =
static_cast<uint32_t
>(lastCandidateCoord[1] + lastCandidateOffset[1]);
1074 lastCandidateCoord[2] =
static_cast<uint32_t
>(lastCandidateCoord[2] + lastCandidateOffset[2]);
1075 uint64_t lastCandidateMorton = PABLO::computeMorton(m_dim, lastCandidateCoord[0], lastCandidateCoord[1], lastCandidateCoord[2]);
1078 if (candidateIdx < getNumOctants()){
1081 u32array3 coordtry = {{0, 0, 0}};
1082 bool isNeighbourCandidate =
true;
1083 for (int8_t idim=0; idim<m_dim; idim++){
1084 coordtry[idim] = m_octants[candidateIdx].getLogicalCoordinates(idim);
1086 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(coordtry[idim] - coord[idim]));
1087 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_octants[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1089 isNeighbourCandidate =
false;
1094 if (isNeighbourCandidate){
1095 bool isNeighbour =
false;
1096 uint8_t leveltry = m_octants[candidateIdx].getLevel();
1097 if (leveltry > level){
1098 array<int64_t,3> coord1 ={{1, 1, 1}} ;
1099 for (int8_t idim=0; idim<m_dim; idim++){
1100 coord1[idim] = coord[idim] + size;
1103 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])))){
1107 else if (leveltry < level){
1108 u32array3 coordtry1 = {{1, 1, 1}};
1109 for (int8_t idim=0; idim<m_dim; idim++){
1110 coordtry1[idim] = coordtry[idim] + m_octants[candidateIdx].getLogicalSize();
1113 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])))){
1119 neighbours.push_back(candidateIdx);
1120 isghost.push_back(
false);
1124 neighArea += m_octants[candidateIdx].getLogicalArea();
1125 if (neighArea == faceArea){
1133 if (candidateIdx > getNumOctants() - 1){
1137 candidateMorton = m_octants[candidateIdx].getMorton();
1138 if (candidateMorton > lastCandidateMorton){
1150 bool ghostSearch = !onlyinternal && (getNumGhosts() > 0);
1152 if (!oct->getIsGhost() && !oct->getPbound(iface)){
1153 ghostSearch =
false;
1160 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_ghosts, &candidateIdx, &candidateMorton);
1163 if(candidateMorton == sameSizeVirtualNeighMorton && m_ghosts[candidateIdx].getLevel() == level){
1164 neighbours.push_back(candidateIdx);
1165 isghost.push_back(
true);
1170 if (candidateIdx < getNumGhosts()){
1173 u32array3 coordtry = {{0, 0, 0}};
1174 bool isNeighbourCandidate =
true;
1175 for (int8_t idim=0; idim<m_dim; idim++){
1176 coordtry[idim] = m_ghosts[candidateIdx].getLogicalCoordinates(idim);
1178 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(coordtry[idim] - coord[idim]));
1179 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_ghosts[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1181 isNeighbourCandidate =
false;
1186 if (isNeighbourCandidate){
1187 bool isNeighbour =
false;
1188 uint8_t leveltry = m_ghosts[candidateIdx].getLevel();
1189 if (leveltry > level){
1190 array<int64_t, 3> coord1 = {{1, 1, 1}};
1191 for (int8_t idim=0; idim<m_dim; idim++){
1192 coord1[idim] = coord[idim] + size;
1195 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])))){
1199 else if (leveltry < level){
1200 u32array3 coordtry1 = {{1, 1, 1}};
1201 for (int8_t idim=0; idim<m_dim; idim++){
1202 coordtry1[idim] = coordtry[idim] + m_ghosts[candidateIdx].getLogicalSize();
1205 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])))){
1211 neighbours.push_back(candidateIdx);
1212 isghost.push_back(
true);
1216 neighArea += m_ghosts[candidateIdx].getLogicalArea();
1217 if (neighArea == faceArea){
1224 if (candidateIdx > getNumGhosts() - 1){
1228 candidateMorton = m_ghosts[candidateIdx].getMorton();
1229 if (candidateMorton > lastCandidateMorton){
1249 LocalTree::findEdgeNeighbours(
const Octant* oct, uint8_t iedge, u32vector & neighbours, bvector & isghost,
bool onlyinternal,
bool append)
const{
1257 if (iedge >= m_treeConstants->nEdges){
1262 bool isperiodic =
false;
1263 if (oct->getEdgeBound(iedge)) {
1264 isperiodic = isEdgePeriodic(oct, iedge);
1271 uint8_t level = oct->getLevel();
1275 neighbours.push_back(0);
1276 isghost.push_back(
false);
1282 uint32_t candidateIdx = 0;
1283 uint64_t candidateMorton = 0;
1285 uint32_t neighSize = 0;
1286 uint32_t edgeSize = oct->getLogicalSize();
1288 uint32_t size = oct->getLogicalSize();
1290 std::array<uint32_t, 3> coord = oct->getLogicalCoordinates();
1293 coord[0] =
static_cast<uint32_t
>(coord[0] + periodicOffset[0]);
1294 coord[1] =
static_cast<uint32_t
>(coord[1] + periodicOffset[1]);
1295 coord[2] =
static_cast<uint32_t
>(coord[2] + periodicOffset[2]);
1298 const int8_t (&cxyz)[3] = m_treeConstants->edgeCoeffs[iedge];
1302 std::array<uint32_t, 3> sameSizeVirtualNeighCoord = coord;
1303 sameSizeVirtualNeighCoord[0] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[0] + sameSizeVirtualNeighOffset[0]);
1304 sameSizeVirtualNeighCoord[1] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[1] + sameSizeVirtualNeighOffset[1]);
1305 sameSizeVirtualNeighCoord[2] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[2] + sameSizeVirtualNeighOffset[2]);
1306 uint64_t sameSizeVirtualNeighMorton = PABLO::computeMorton(m_dim, sameSizeVirtualNeighCoord[0], sameSizeVirtualNeighCoord[1], sameSizeVirtualNeighCoord[2]);
1313 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_octants, &candidateIdx, &candidateMorton);
1316 if(candidateMorton == sameSizeVirtualNeighMorton && m_octants[candidateIdx].m_level == level){
1317 isghost.push_back(
false);
1318 neighbours.push_back(candidateIdx);
1328 std::array<uint32_t, 3> lastCandidateCoord = coord;
1329 lastCandidateCoord[0] =
static_cast<uint32_t
>(lastCandidateCoord[0] + lastCandidateOffset[0]);
1330 lastCandidateCoord[1] =
static_cast<uint32_t
>(lastCandidateCoord[1] + lastCandidateOffset[1]);
1331 lastCandidateCoord[2] =
static_cast<uint32_t
>(lastCandidateCoord[2] + lastCandidateOffset[2]);
1332 uint64_t lastCandidateMorton = PABLO::computeMorton(m_dim, lastCandidateCoord[0], lastCandidateCoord[1], lastCandidateCoord[2]);
1335 if (candidateIdx < getNumOctants()) {
1338 u32array3 coordtry = {{0, 0, 0}};
1339 bool isNeighbourCandidate =
true;
1340 for (int8_t idim=0; idim<m_dim; idim++){
1341 coordtry[idim] = m_octants[candidateIdx].getLogicalCoordinates(idim);
1343 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(-int32_t(coord[idim]) + int32_t(coordtry[idim])));
1344 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_octants[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1347 isNeighbourCandidate =
false;
1352 if (isNeighbourCandidate){
1353 bool isNeighbour =
false;
1354 uint8_t leveltry = m_octants[candidateIdx].getLevel();
1355 if (leveltry > level){
1356 u32array3 coord1 = {{1, 1, 1}};
1357 for (int8_t idim=0; idim<m_dim; idim++){
1358 coord1[idim] = coord[idim] + size;
1361 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])))){
1365 else if (leveltry < level){
1366 u32array3 coordtry1 = {{1, 1, 1}};
1367 for (int8_t idim=0; idim<m_dim; idim++){
1368 coordtry1[idim] = coordtry[idim] + m_octants[candidateIdx].getLogicalSize();
1371 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])))){
1377 neighbours.push_back(candidateIdx);
1378 isghost.push_back(
false);
1382 neighSize += m_octants[candidateIdx].getLogicalSize();
1383 if (neighSize == edgeSize){
1391 if (candidateIdx > getNumOctants()-1){
1395 candidateMorton = m_octants[candidateIdx].getMorton();
1396 if (candidateMorton > lastCandidateMorton){
1405 if (getNumGhosts() > 0 && !onlyinternal){
1407 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_ghosts, &candidateIdx, &candidateMorton);
1410 if(candidateMorton == sameSizeVirtualNeighMorton && m_ghosts[candidateIdx].m_level == level){
1411 isghost.push_back(
true);
1412 neighbours.push_back(candidateIdx);
1417 if (candidateIdx < getNumGhosts()){
1420 u32array3 coordtry = {{0, 0, 0}};
1421 bool isNeighbourCandidate =
true;
1422 for (int8_t idim=0; idim<m_dim; idim++){
1423 coordtry[idim] = m_ghosts[candidateIdx].getLogicalCoordinates(idim);
1425 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(-int32_t(coord[idim]) + int32_t(coordtry[idim])));
1426 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_ghosts[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1429 isNeighbourCandidate =
false;
1434 if (isNeighbourCandidate){
1435 bool isNeighbour =
false;
1436 uint8_t leveltry = m_ghosts[candidateIdx].getLevel();
1437 if (leveltry > level){
1438 u32array3 coord1 = {{1, 1, 1}};
1439 for (int8_t idim=0; idim<m_dim; idim++){
1440 coord1[idim] = int32_t(coord[idim]) + size;
1443 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])))){
1447 else if (leveltry < level){
1448 u32array3 coordtry1 = {{1, 1, 1}};
1449 for (int8_t idim=0; idim<m_dim; idim++){
1450 coordtry1[idim] = coordtry[idim] + m_ghosts[candidateIdx].getLogicalSize();
1453 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])))){
1459 neighbours.push_back(candidateIdx);
1460 isghost.push_back(
true);
1464 neighSize += m_ghosts[candidateIdx].getLogicalSize();
1465 if (neighSize == edgeSize){
1473 if (candidateIdx > getNumGhosts()-1){
1477 candidateMorton = m_ghosts[candidateIdx].getMorton();
1478 if (candidateMorton > lastCandidateMorton){
1498 LocalTree::findNodeNeighbours(
const Octant* oct, uint8_t inode, u32vector & neighbours, bvector & isghost,
bool onlyinternal,
bool append)
const{
1506 if (inode >= m_treeConstants->nNodes){
1511 bool isperiodic =
false;
1512 if (oct->getNodeBound(inode)) {
1513 isperiodic = isNodePeriodic(oct, inode);
1520 uint8_t level = oct->getLevel();
1524 neighbours.push_back(0);
1525 isghost.push_back(
false);
1531 uint32_t candidateIdx = 0;
1532 uint64_t candidateMorton = 0;
1534 uint32_t size = oct->getLogicalSize();
1536 std::array<uint32_t, 3> coord = oct->getLogicalCoordinates();
1539 coord[0] =
static_cast<uint32_t
>(coord[0] + periodicOffset[0]);
1540 coord[1] =
static_cast<uint32_t
>(coord[1] + periodicOffset[1]);
1541 coord[2] =
static_cast<uint32_t
>(coord[2] + periodicOffset[2]);
1544 const int8_t (&cxyz)[3] = m_treeConstants->nodeCoeffs[inode];
1548 std::array<uint32_t, 3> sameSizeVirtualNeighCoord = coord;
1549 sameSizeVirtualNeighCoord[0] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[0] + sameSizeVirtualNeighOffset[0]);
1550 sameSizeVirtualNeighCoord[1] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[1] + sameSizeVirtualNeighOffset[1]);
1551 sameSizeVirtualNeighCoord[2] =
static_cast<uint32_t
>(sameSizeVirtualNeighCoord[2] + sameSizeVirtualNeighOffset[2]);
1552 uint64_t sameSizeVirtualNeighMorton = PABLO::computeMorton(m_dim, sameSizeVirtualNeighCoord[0], sameSizeVirtualNeighCoord[1], sameSizeVirtualNeighCoord[2]);
1559 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_octants, &candidateIdx, &candidateMorton);
1562 if(candidateMorton == sameSizeVirtualNeighMorton && m_octants[candidateIdx].m_level == oct->m_level){
1563 isghost.push_back(
false);
1564 neighbours.push_back(candidateIdx);
1574 std::array<uint32_t, 3> lastCandidateCoord = coord;
1575 lastCandidateCoord[0] =
static_cast<uint32_t
>(lastCandidateCoord[0] + lastCandidateOffset[0]);
1576 lastCandidateCoord[1] =
static_cast<uint32_t
>(lastCandidateCoord[1] + lastCandidateOffset[1]);
1577 lastCandidateCoord[2] =
static_cast<uint32_t
>(lastCandidateCoord[2] + lastCandidateOffset[2]);
1578 uint64_t lastCandidateMorton = PABLO::computeMorton(m_dim, lastCandidateCoord[0], lastCandidateCoord[1], lastCandidateCoord[2]);
1581 if (candidateIdx < getNumOctants()) {
1584 u32array3 coordtry = {{0, 0, 0}};
1585 bool isNeighbour =
true;
1586 for (int8_t idim=0; idim<m_dim; idim++){
1587 coordtry[idim] = m_octants[candidateIdx].getLogicalCoordinates(idim);
1589 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(-int32_t(coord[idim]) + int32_t(coordtry[idim])));
1590 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_octants[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1593 isNeighbour =
false;
1600 neighbours.push_back(candidateIdx);
1601 isghost.push_back(
false);
1606 if (candidateIdx > getNumOctants()-1){
1610 candidateMorton = m_octants[candidateIdx].getMorton();
1611 if (candidateMorton > lastCandidateMorton){
1621 if (getNumGhosts() > 0 && !onlyinternal){
1623 computeNeighSearchBegin(sameSizeVirtualNeighMorton, m_ghosts, &candidateIdx, &candidateMorton);
1626 if(candidateMorton == sameSizeVirtualNeighMorton && m_ghosts[candidateIdx].m_level == oct->m_level){
1627 isghost.push_back(
true);
1628 neighbours.push_back(candidateIdx);
1633 if (candidateIdx < getNumGhosts()) {
1636 u32array3 coordtry = {{0, 0, 0}};
1637 bool isNeighbour =
true;
1638 for (int8_t idim=0; idim<m_dim; idim++){
1639 coordtry[idim] = m_ghosts[candidateIdx].getLogicalCoordinates(idim);
1641 int32_t Dx = int32_t(int32_t(
abs(cxyz[idim]))*(-int32_t(coord[idim]) + int32_t(coordtry[idim])));
1642 int32_t Dxstar = int32_t((cxyz[idim]-1)/2)*(m_ghosts[candidateIdx].getLogicalSize()) + int32_t((cxyz[idim]+1)/2)*size;
1645 isNeighbour =
false;
1652 neighbours.push_back(candidateIdx);
1653 isghost.push_back(
true);
1658 if (candidateIdx > getNumGhosts()-1){
1662 candidateMorton = m_ghosts[candidateIdx].getMorton();
1663 if (candidateMorton > lastCandidateMorton){
1689 LocalTree::computeNeighSearchBegin(uint64_t sameSizeVirtualNeighMorton,
const octvector &octants, uint32_t *searchBeginIdx, uint64_t *searchBeginMorton)
const {
1692 if (octants.empty()) {
1693 *searchBeginIdx = 0;
1694 *searchBeginMorton = PABLO::INVALID_MORTON;
1702 uint32_t lowerBoundIdx;
1703 uint64_t lowerBoundMorton;
1704 findMortonLowerBound(sameSizeVirtualNeighMorton, octants, &lowerBoundIdx, &lowerBoundMorton);
1706 if (lowerBoundMorton == sameSizeVirtualNeighMorton || lowerBoundIdx == 0) {
1707 *searchBeginIdx = lowerBoundIdx;
1708 *searchBeginMorton = lowerBoundMorton;
1710 *searchBeginIdx = lowerBoundIdx - 1;
1711 *searchBeginMorton = octants[*searchBeginIdx].getMorton();
1726 LocalTree::fixBrokenFamiliesMarkers(std::vector<Octant *> *updatedOctants, std::vector<bool> *updatedGhostFlags){
1729 bool updated =
false;
1731 uint32_t nocts = m_octants.size();
1736 uint32_t nghosts = m_ghosts.size();
1741 uint32_t idx1_gh = 0;
1742 uint32_t idx2_gh = 0;
1743 uint32_t last_idx =nocts-1;
1746 Octant father(m_dim);
1749 m_lastGhostBros.clear();
1750 m_firstGhostBros.clear();
1753 bool checkend =
true;
1754 bool checkstart =
true;
1757 while(m_ghosts[idx2_gh].getMorton() <= m_lastDescMorton){
1759 if (idx2_gh > nghosts-1)
break;
1761 if (idx2_gh > nghosts-1) checkend =
false;
1763 while(m_ghosts[idx1_gh].getMorton() <= m_octants[0].getMorton()){
1765 if (idx1_gh > nghosts-1)
break;
1767 if (idx1_gh == 0) checkstart =
false;
1772 if (m_ghosts[idx1_gh].buildFather()==m_octants[0].buildFather()){
1773 father = m_ghosts[idx1_gh].buildFather();
1776 int8_t marker = m_ghosts[idx].getMarker();
1777 while(marker < 0 && m_ghosts[idx].buildFather() == father){
1780 m_firstGhostBros.push_back(idx);
1786 marker = m_ghosts[idx].getMarker();
1789 while(idx<nocts && m_octants[idx].buildFather() == father){
1790 if (m_octants[idx].getMarker()<0)
1796 if (nbro != m_treeConstants->nChildren && idx!=nocts){
1797 for(uint32_t ii=0; ii<idx; ii++){
1798 Octant &octant = m_octants[ii];
1799 if (octant.getMarker()<0){
1800 octant.setMarker(0);
1801 if (updatedOctants) {
1802 updatedOctants->push_back(&octant);
1804 if (updatedGhostFlags) {
1805 updatedGhostFlags->push_back(
false);
1811 m_firstGhostBros.clear();
1817 bool checklocal =
false;
1818 if (m_ghosts[idx2_gh].buildFather()==m_octants[nocts-1].buildFather()){
1819 father = m_ghosts[idx2_gh].buildFather();
1825 int8_t marker = m_ghosts[idx].getMarker();
1826 while(marker < 0 && m_ghosts[idx].buildFather() == father){
1829 m_lastGhostBros.push_back(idx);
1836 marker = m_ghosts[idx].getMarker();
1840 while(m_octants[idx].buildFather() == father){
1841 if (m_octants[idx].getMarker()<0)
1849 if (nbro != m_treeConstants->nChildren && idx!=nocts-1){
1850 for(uint32_t ii=idx+1; ii<nocts; ii++){
1851 Octant &octant = m_octants[ii];
1852 if (octant.getMarker()<0){
1853 octant.setMarker(0);
1854 if (updatedOctants) {
1855 updatedOctants->push_back(&octant);
1857 if (updatedGhostFlags) {
1858 updatedGhostFlags->push_back(
false);
1864 m_lastGhostBros.clear();
1871 father = m_octants[0].buildFather();
1872 uint64_t mortonld = father.computeLastDescMorton();
1874 for (idx=0; idx<m_treeConstants->nChildren; idx++){
1877 if (m_octants[idx].getMorton() <= mortonld){
1883 if (nbro != m_treeConstants->nChildren) {
1888 for (idx=idx0; idx<nocts; idx++){
1889 Octant &octant = m_octants[idx];
1890 if(octant.getMarker() < 0 && octant.getLevel() > 0){
1892 father = octant.buildFather();
1894 for (idx2=idx; idx2<idx+m_treeConstants->nChildren; idx2++){
1896 if(m_octants[idx2].getMarker() < 0 && m_octants[idx2].buildFather() == father){
1901 if (nbro == m_treeConstants->nChildren){
1906 octant.setMarker(0);
1907 if (updatedOctants) {
1908 updatedOctants->push_back(&octant);
1910 if (updatedGhostFlags) {
1911 updatedGhostFlags->push_back(
false);
1931 LocalTree::localBalance(
bool doNew,
bool checkInterior,
bool checkGhost){
1933 bool balanceEdges = ((m_balanceCodim>1) && (m_dim==3));
1934 bool balanceNodes = (m_balanceCodim==m_dim);
1936 std::vector<Octant *> processOctants;
1937 std::vector<bool> processGhostFlags;
1941 for (Octant &octant : m_octants){
1943 bool balanceOctant = octant.getBalance();
1944 if (balanceOctant) {
1946 balanceOctant = (octant.getMarker() != 0) || octant.getIsNewC() || octant.getIsNewR();
1948 balanceOctant = (octant.getMarker() != 0);
1952 if (!balanceOctant) {
1957 processOctants.push_back(&octant);
1958 processGhostFlags.push_back(
false);
1971 for (Octant &octant : m_ghosts){
1973 if (octant.getGhostLayer() > 0) {
1978 processOctants.push_back(&octant);
1979 processGhostFlags.push_back(
true);
1984 std::vector<uint32_t> neighs;
1985 std::vector<bool> neighGhostFlags;
1987 bool updated =
false;
1988 std::vector<Octant *> updatedProcessOctants;
1989 std::vector<bool> updatedProcessGhostFlags;
1990 while (!processOctants.empty()) {
1992 bool brokenFamilieisFixed = fixBrokenFamiliesMarkers(&processOctants, &processGhostFlags);
1993 if (brokenFamilieisFixed) {
1998 std::size_t processSize = processOctants.size();
1999 for (std::size_t n = 0; n < processSize; ++n) {
2000 Octant &octant = *(processOctants[n]);
2001 bool ghostFlag = processGhostFlags[n];
2005 neighGhostFlags.clear();
2007 for (
int iface=0; iface < m_treeConstants->nFaces; iface++) {
2008 findNeighbours(&octant, iface, neighs, neighGhostFlags, ghostFlag,
true);
2012 for (
int inode=0; inode < m_treeConstants->nNodes; inode++) {
2013 findNodeNeighbours(&octant, inode, neighs, neighGhostFlags, ghostFlag,
true);
2018 for (
int iedge=0; iedge < m_treeConstants->nEdges; iedge++) {
2019 findEdgeNeighbours(&octant, iedge, neighs, neighGhostFlags, ghostFlag,
true);
2024 int8_t level = octant.getLevel();
2025 int8_t futureLevel = std::min(m_treeConstants->maxLevel,
static_cast<int8_t
>(level + octant.getMarker()));
2027 std::size_t nNeighs = neighs.size();
2028 for(std::size_t i = 0; i < nNeighs; i++){
2029 bool neighGhostFlag = neighGhostFlags[i];
2030 Octant &neighOctant = (neighGhostFlag ? m_ghosts[neighs[i]]: m_octants[neighs[i]]);
2032 int8_t neighLevel = neighOctant.getLevel();
2033 int8_t neighFutureLevel = std::min(m_treeConstants->maxLevel, int8_t(neighLevel + neighOctant.getMarker()));
2034 if(!ghostFlag && futureLevel < neighFutureLevel - 1) {
2035 futureLevel = neighFutureLevel - 1;
2036 octant.setMarker(futureLevel - level);
2037 updatedProcessOctants.push_back(&octant);
2038 updatedProcessGhostFlags.push_back(ghostFlag);
2041 else if(!neighGhostFlag && neighFutureLevel < futureLevel - 1) {
2042 neighOctant.setMarker((futureLevel - 1) - neighLevel);
2043 if (neighOctant.getBalance()) {
2044 updatedProcessOctants.push_back(&neighOctant);
2045 updatedProcessGhostFlags.push_back(neighGhostFlag);
2053 updatedProcessOctants.swap(processOctants);
2054 updatedProcessGhostFlags.swap(processGhostFlags);
2056 updatedProcessOctants.clear();
2057 updatedProcessGhostFlags.clear();
2076 const int8_t (&normalizedOffsets)[3] = m_treeConstants->normals[iface];
2079 uint32_t size = m_treeConstants->lengths[level];
2080 uint32_t neighSize = m_treeConstants->lengths[neighLevel];
2083 std::array<int64_t, 3> neighOffsets;
2084 for (
int i = 0; i < 3; ++i) {
2085 neighOffsets[i] = normalizedOffsets[i];
2086 if (neighOffsets[i] > 0) {
2087 neighOffsets[i] *= size;
2089 neighOffsets[i] *= neighSize;
2093 return neighOffsets;
2107 uint32_t size = m_treeConstants->lengths[level];
2108 uint32_t neighSize = m_treeConstants->lengths[neighLevel];
2113 uint32_t delta = size - neighSize;
2117 neighOffsets[1] += delta;
2118 neighOffsets[2] += delta;
2123 neighOffsets[0] += delta;
2124 neighOffsets[2] += delta;
2129 neighOffsets[0] += delta;
2130 neighOffsets[1] += delta;
2134 return neighOffsets;
2148 uint32_t neighSize = m_treeConstants->lengths[neighLevel];
2173 int nNeighsDirection1 = 1 << (neighLevel - level);
2174 int nNeighsDirection2 = (m_dim > 2) ? nNeighsDirection1 : 1;
2175 int nNeighs = nNeighsDirection1 * nNeighsDirection2;
2180 for (
int j = 0; j < nNeighsDirection2; ++j) {
2181 for (
int i = 0; i < nNeighsDirection1; ++i) {
2182 (*neighOffsets)[k][direction1] += i * neighSize;
2183 (*neighOffsets)[k][direction2] += j * neighSize;
2200 const int8_t (&normalizedOffsets)[3] = m_treeConstants->nodeCoeffs[inode];
2203 uint32_t size = m_treeConstants->lengths[level];
2204 uint32_t neighSize = m_treeConstants->lengths[neighLevel];
2207 std::array<int64_t, 3> neighOffsets;
2208 for (
int i = 0; i < 3; ++i) {
2209 neighOffsets[i] = normalizedOffsets[i];
2210 if (neighOffsets[i] > 0) {
2211 neighOffsets[i] *= size;
2213 neighOffsets[i] *= neighSize;
2217 return neighOffsets;
2257 const int8_t (&normalizedOffsets)[3] = m_treeConstants->edgeCoeffs[iedge];
2260 uint32_t size = m_treeConstants->lengths[level];
2261 uint32_t neighSize = m_treeConstants->lengths[neighLevel];
2264 std::array<int64_t, 3> neighOffsets;
2265 for (
int i = 0; i < 3; ++i) {
2266 neighOffsets[i] = normalizedOffsets[i];
2267 if (neighOffsets[i] > 0) {
2268 neighOffsets[i] *= size;
2270 neighOffsets[i] *= neighSize;
2274 return neighOffsets;
2288 uint32_t size = m_treeConstants->lengths[level];
2289 uint32_t neighSize = m_treeConstants->lengths[neighLevel];
2294 uint32_t offset = size - neighSize;
2300 neighOffsets[1] += offset;
2307 neighOffsets[0] += offset;
2314 neighOffsets[2] += offset;
2318 return neighOffsets;
2332 uint32_t neighSize = m_treeConstants->lengths[neighLevel];
2357 int nNeighs = 1 << (neighLevel - level);
2359 for (
int i = 1; i < nNeighs; ++i) {
2360 (*neighOffsets)[i][direction] += i * neighSize;
2375 std::array<int64_t, 3> offset = {{0, 0, 0}};
2376 if (!isPeriodic(&octant, iface)) {
2380 int64_t maxLength = m_treeConstants->lengths[0];
2381 const int8_t (&referenceOffset)[3] = m_treeConstants->normals[iface];
2383 for (
int d = 0; d < m_dim; ++d) {
2384 offset[d] = - maxLength *
static_cast<int64_t
>(referenceOffset[d]);
2399 std::array<int64_t, 3> offset = {{0, 0, 0}};
2400 for (
int i = 0; i < m_dim; ++i) {
2401 uint8_t face = m_treeConstants->nodeFace[inode][i];
2402 if (!isPeriodic(&octant, face)) {
2407 for (
int d = 0; d < m_dim; ++d) {
2408 offset[d] += faceOffset[d];
2424 std::array<int64_t, 3> offset = {{0, 0, 0}};
2425 for (uint8_t face : m_treeConstants->edgeFace[iedge]) {
2426 if (!isPeriodic(&octant, face)) {
2431 for (
int d = 0; d < m_dim; ++d) {
2432 offset[d] += faceOffset[d];
2452 return m_treeConstants->maxLevel;
2464 if (octant.
getBalance() && m_balanceCodim == m_dim) {
2467 return m_treeConstants->maxLevel;
2479 if (octant.
getBalance() && m_balanceCodim > 1) {
2482 return m_treeConstants->maxLevel;
2491 LocalTree::computeIntersections() {
2493 octvector::iterator it, obegin, oend;
2495 u32vector neighbours;
2496 vector<bool> isghost;
2499 uint8_t iface, iface2;
2501 m_intersections.clear();
2502 m_intersections.reserve(2*3*m_octants.size());
2507 obegin = m_ghosts.begin();
2508 oend = m_ghosts.end();
2509 for (it = obegin; it != oend; ++it){
2510 for (iface = 0; iface < m_dim; iface++){
2512 findNeighbours(m_ghosts.data() + idx, iface2, neighbours, isghost,
true,
false);
2513 nsize = neighbours.size();
2514 if (!(it->m_info[iface2])){
2516 for (i = 0; i < nsize; i++){
2517 intersection.m_dim = m_dim;
2518 intersection.m_finer = getGhostLevel(idx) >= getLevel((
int)neighbours[i]);
2519 intersection.m_out = intersection.m_finer;
2520 intersection.m_outisghost = intersection.m_finer;
2521 intersection.m_owners[0] = neighbours[i];
2522 intersection.m_owners[1] = idx;
2523 intersection.m_iface = m_treeConstants->
oppositeFace[iface2] - (getGhostLevel(idx) >= getLevel((
int)neighbours[i]));
2524 intersection.m_isnew =
false;
2525 intersection.m_isghost =
true;
2526 intersection.m_bound =
false;
2527 intersection.m_pbound =
true;
2528 m_intersections.push_back(intersection);
2533 for (i = 0; i < nsize; i++){
2534 intersection.m_dim = m_dim;
2535 intersection.m_finer = getGhostLevel(idx) >= getLevel((
int)neighbours[i]);
2536 intersection.m_out = intersection.m_finer;
2537 intersection.m_outisghost = intersection.m_finer;
2538 intersection.m_owners[0] = neighbours[i];
2539 intersection.m_owners[1] = idx;
2540 intersection.m_iface = m_treeConstants->oppositeFace[iface2] - (getGhostLevel(idx) >= getLevel((
int)neighbours[i]));
2541 intersection.m_isnew =
false;
2542 intersection.m_isghost =
true;
2543 intersection.m_bound =
true;
2544 intersection.m_pbound =
true;
2545 m_intersections.push_back(intersection);
2554 obegin = m_octants.begin();
2555 oend = m_octants.end();
2556 for (it = obegin; it != oend; ++it){
2557 for (iface = 0; iface < m_dim; iface++){
2559 findNeighbours(m_octants.data() + idx, iface2, neighbours, isghost,
false,
false);
2560 nsize = neighbours.size();
2562 if (!(it->m_info[iface2])){
2564 for (i = 0; i < nsize; i++){
2566 intersection.m_dim = m_dim;
2567 intersection.m_owners[0] = idx;
2568 intersection.m_owners[1] = neighbours[i];
2569 intersection.m_finer = (nsize>1);
2570 intersection.m_out = (nsize>1);
2571 intersection.m_outisghost = (nsize>1);
2572 intersection.m_iface = iface2 + (nsize>1);
2573 intersection.m_isnew =
false;
2574 intersection.m_isghost =
true;
2575 intersection.m_bound =
false;
2576 intersection.m_pbound =
true;
2577 m_intersections.push_back(intersection);
2580 intersection.m_dim = m_dim;
2581 intersection.m_owners[0] = idx;
2582 intersection.m_owners[1] = neighbours[i];
2583 intersection.m_finer = (nsize>1);
2584 intersection.m_out = (nsize>1);
2585 intersection.m_outisghost =
false;
2586 intersection.m_iface = iface2 + (nsize>1);
2587 intersection.m_isnew =
false;
2588 intersection.m_isghost =
false;
2589 intersection.m_bound =
false;
2590 intersection.m_pbound =
false;
2591 m_intersections.push_back(intersection);
2597 for (i = 0; i < nsize; i++){
2599 intersection.m_dim = m_dim;
2600 intersection.m_owners[0] = idx;
2601 intersection.m_owners[1] = neighbours[i];
2602 intersection.m_finer = (nsize>1);
2603 intersection.m_out = intersection.m_finer;
2604 intersection.m_outisghost = intersection.m_finer;
2605 intersection.m_iface = iface2 + (nsize>1);
2606 intersection.m_isnew =
false;
2607 intersection.m_isghost =
true;
2608 intersection.m_bound =
true;
2609 intersection.m_pbound =
true;
2610 m_intersections.push_back(intersection);
2613 intersection.m_dim = m_dim;
2614 intersection.m_owners[0] = idx;
2615 intersection.m_owners[1] = neighbours[i];
2616 intersection.m_finer = (nsize>1);
2617 intersection.m_out = intersection.m_finer;
2618 intersection.m_outisghost =
false;
2619 intersection.m_iface = iface2 + (nsize>1);
2620 intersection.m_isnew =
false;
2621 intersection.m_isghost =
false;
2622 intersection.m_bound =
true;
2623 intersection.m_pbound =
false;
2624 m_intersections.push_back(intersection);
2631 intersection.m_dim = m_dim;
2632 intersection.m_owners[0] = idx;
2633 intersection.m_owners[1] = idx;
2634 intersection.m_finer = 0;
2635 intersection.m_out = 0;
2636 intersection.m_outisghost =
false;
2637 intersection.m_iface = iface2;
2638 intersection.m_isnew =
false;
2639 intersection.m_isghost =
false;
2640 intersection.m_bound =
true;
2641 intersection.m_pbound =
false;
2642 m_intersections.push_back(intersection);
2644 if (it->m_info[iface2+1]){
2645 if (!(m_periodic[iface2+1])){
2647 intersection.m_dim = m_dim;
2648 intersection.m_owners[0] = idx;
2649 intersection.m_owners[1] = idx;
2650 intersection.m_finer = 0;
2651 intersection.m_out = 0;
2652 intersection.m_outisghost =
false;
2653 intersection.m_iface = iface2+1;
2654 intersection.m_isnew =
false;
2655 intersection.m_isghost =
false;
2656 intersection.m_bound =
true;
2657 intersection.m_pbound =
false;
2658 m_intersections.push_back(intersection);
2662 findNeighbours(m_octants.data() + idx, iface2+1, neighbours, isghost,
false,
false);
2663 nsize = neighbours.size();
2664 for (i = 0; i < nsize; i++){
2666 intersection.m_dim = m_dim;
2667 intersection.m_owners[0] = idx;
2668 intersection.m_owners[1] = neighbours[i];
2669 intersection.m_finer = (nsize>1);
2670 intersection.m_out = intersection.m_finer;
2671 intersection.m_outisghost = intersection.m_finer;
2672 intersection.m_iface = iface2 + (nsize>1);
2673 intersection.m_isnew =
false;
2674 intersection.m_isghost =
true;
2675 intersection.m_bound =
true;
2676 intersection.m_pbound =
true;
2677 m_intersections.push_back(intersection);
2680 intersection.m_dim = m_dim;
2681 intersection.m_owners[0] = idx;
2682 intersection.m_owners[1] = neighbours[i];
2683 intersection.m_finer = (nsize>1);
2684 intersection.m_out = intersection.m_finer;
2685 intersection.m_outisghost =
false;
2686 intersection.m_iface = iface2 + (nsize>1);
2687 intersection.m_isnew =
false;
2688 intersection.m_isghost =
false;
2689 intersection.m_bound =
true;
2690 intersection.m_pbound =
false;
2691 m_intersections.push_back(intersection);
2699 intervector(m_intersections).swap(m_intersections);
2708 LocalTree::findMorton(uint64_t targetMorton)
const {
2709 return findMorton(targetMorton, m_octants);
2718 LocalTree::findGhostMorton(uint64_t targetMorton)
const {
2719 return findMorton(targetMorton, m_ghosts);
2732 LocalTree::findMorton(uint64_t targetMorton,
const octvector &octants)
const {
2734 uint32_t lowerBoundIdx;
2735 uint64_t lowerBoundMorton;
2736 findMortonLowerBound(targetMorton, octants, &lowerBoundIdx, &lowerBoundMorton);
2739 if (lowerBoundMorton == targetMorton) {
2740 targetIdx = lowerBoundIdx;
2742 targetIdx = octants.size();
2767 LocalTree::findMortonLowerBound(uint64_t targetMorton,
const octvector &octants, uint32_t *lowerBoundIdx, uint64_t *lowerBoundMorton)
const {
2769 uint32_t nOctants = octants.size();
2771 uint32_t lowIndex = 0;
2772 uint32_t highIndex = nOctants;
2773 uint32_t midIndex = nOctants;
2774 uint64_t midMorton = PABLO::INVALID_MORTON;
2775 while (lowIndex < highIndex) {
2776 midIndex = lowIndex + (highIndex - lowIndex) / 2;
2777 midMorton = octants[midIndex].getMorton();
2778 if (targetMorton < midMorton) {
2779 highIndex = midIndex;
2781 else if (targetMorton > midMorton) {
2782 lowIndex = midIndex + 1;
2785 *lowerBoundIdx = midIndex;
2786 *lowerBoundMorton = midMorton;
2792 *lowerBoundIdx = lowIndex;
2793 if (*lowerBoundIdx == midIndex) {
2794 *lowerBoundMorton = midMorton;
2796 else if (*lowerBoundIdx < nOctants) {
2797 *lowerBoundMorton = octants[*lowerBoundIdx].getMorton();
2800 *lowerBoundMorton = PABLO::INVALID_MORTON;
2822 LocalTree::findMortonUpperBound(uint64_t targetMorton,
const octvector &octants, uint32_t *upperBoundIdx, uint64_t *upperBoundMorton)
const {
2824 uint32_t nOctants = octants.size();
2826 uint32_t lowIndex = 0;
2827 uint32_t highIndex = nOctants;
2828 uint32_t midIndex = nOctants;
2829 uint64_t midMorton = PABLO::INVALID_MORTON;
2830 while (lowIndex < highIndex) {
2831 midIndex = lowIndex + (highIndex - lowIndex) / 2;
2832 midMorton = octants[midIndex].getMorton();
2833 if (targetMorton < midMorton) {
2834 highIndex = midIndex;
2837 lowIndex = midIndex + 1;
2841 *upperBoundIdx = lowIndex;
2842 if (*upperBoundIdx == midIndex) {
2843 *upperBoundMorton = midMorton;
2845 else if (*upperBoundIdx < nOctants) {
2846 *upperBoundMorton = octants[*upperBoundIdx].getMorton();
2849 *upperBoundMorton = PABLO::INVALID_MORTON;
2859 LocalTree::computeConnectivity(){
2860 vector<uint64_t> nodeKeys;
2861 unordered_map<uint64_t, array<uint32_t, 3> > nodeCoords;
2862 unordered_map<uint64_t, vector<uint64_t> > nodeOctants;
2863 uint32_t noctants = getNumOctants();
2864 uint32_t nghosts = getNumGhosts();
2869 nodeKeys.reserve(noctants);
2870 nodeCoords.reserve(noctants);
2871 nodeOctants.reserve(noctants);
2873 for (uint64_t n = 0; n < (noctants + nghosts); n++){
2874 const Octant *octant;
2876 uint32_t octantId =
static_cast<uint32_t
>(n);
2877 octant = &(m_octants[octantId]);
2879 uint32_t octantId =
static_cast<uint32_t
>(n - noctants);
2880 octant = &(m_ghosts[octantId]);
2883 for (uint8_t i = 0; i < m_treeConstants->nNodes; ++i){
2885 octant->getLogicalNode(node, i);
2887 uint64_t nodeKey = octant->computeNodePersistentKey(node);
2888 if (nodeCoords.count(nodeKey) == 0) {
2889 nodeKeys.push_back(nodeKey);
2890 nodeCoords.insert({{nodeKey, std::move(node)}});
2891 nodeOctants[nodeKey].reserve(m_treeConstants->nNodes);
2894 nodeOctants[nodeKey].push_back(n);
2897 std::sort(nodeKeys.begin(), nodeKeys.end());
2901 m_connectivity.clear();
2902 m_ghostsConnectivity.clear();
2904 m_nodes.reserve(nodeKeys.size());
2905 m_connectivity.resize(noctants);
2906 m_ghostsConnectivity.resize(nghosts);
2908 uint32_t nodeId = 0;
2909 for (uint64_t nodeKey : nodeKeys) {
2910 m_nodes.emplace_back(std::move(nodeCoords.at(nodeKey)));
2911 for (uint64_t n : nodeOctants.at(nodeKey)) {
2912 std::vector<uint32_t> *octantConnect;
2914 uint32_t octantId =
static_cast<uint32_t
>(n);
2915 octantConnect = &(m_connectivity[octantId]);
2917 uint32_t octantId =
static_cast<uint32_t
>(n - noctants);
2918 octantConnect = &(m_ghostsConnectivity[octantId]);
2921 if (octantConnect->size() == 0) {
2922 octantConnect->reserve(m_treeConstants->nNodes);
2924 octantConnect->push_back(nodeId);
2929 m_nodes.shrink_to_fit();
2938 LocalTree::clearConnectivity(
bool release){
2941 u32vector2D().swap(m_connectivity);
2942 u32vector2D().swap(m_ghostsConnectivity);
2945 m_connectivity.clear();
2946 m_ghostsConnectivity.clear();
2953 LocalTree::updateConnectivity(){
2954 clearConnectivity(
false);
2955 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 > > &)
static BITPIT_PUBLIC_API const TreeConstants & instance(uint8_t dim)