|
@@ -239,7 +239,7 @@ template <class Real, Integer DIM> class Tree {
|
|
|
return comm;
|
|
|
}
|
|
|
|
|
|
- void UpdateRefinement(const Vector<Real>& coord, Long M = 1) {
|
|
|
+ void UpdateRefinement(const Vector<Real>& coord, Long M = 1, bool balance21 = 0, bool periodic = 0) {
|
|
|
Integer np = comm.Size();
|
|
|
Integer rank = comm.Rank();
|
|
|
|
|
@@ -311,7 +311,10 @@ template <class Real, Integer DIM> class Tree {
|
|
|
while (m0 < mend) {
|
|
|
Integer d = m0.Depth();
|
|
|
Morton<DIM> m1 = (idx + M < pt_mid.Dim() ? pt_mid[idx+M] : Morton<DIM>().Next());
|
|
|
- while (d < Morton<DIM>::MAX_DEPTH && m0.Ancestor(d) == m1.Ancestor(d)) d++;
|
|
|
+ while (d < Morton<DIM>::MAX_DEPTH && m0.Ancestor(d) == m1.Ancestor(d)) {
|
|
|
+ node_mid.PushBack(m0.Ancestor(d));
|
|
|
+ d++;
|
|
|
+ }
|
|
|
m0 = m0.Ancestor(d);
|
|
|
node_mid.PushBack(m0);
|
|
|
m0 = m0.Next();
|
|
@@ -325,18 +328,73 @@ template <class Real, Integer DIM> class Tree {
|
|
|
Morton<DIM> m0 = coarsest_ancestor_mid(node_mid[min_idx]);
|
|
|
comm.Allgather(Ptr2ConstItr<Morton<DIM>>(&m0,1), 1, mins.begin(), 1);
|
|
|
}
|
|
|
+ if (balance21) { // 2:1 balance refinement // TODO: optimize
|
|
|
+ Vector<Morton<DIM>> parent_mid;
|
|
|
+ { // add balancing Morton IDs
|
|
|
+ Vector<std::set<Morton<DIM>>> parent_mid_set(Morton<DIM>::MAX_DEPTH+1);
|
|
|
+ Vector<Morton<DIM>> nlst;
|
|
|
+ for (const auto& m0 : node_mid) {
|
|
|
+ Integer d0 = m0.Depth();
|
|
|
+ parent_mid_set[m0.Depth()].insert(m0.Ancestor(d0-1));
|
|
|
+ }
|
|
|
+ for (Integer d = Morton<DIM>::MAX_DEPTH; d > 0; d--) {
|
|
|
+ for (const auto& m : parent_mid_set[d]) {
|
|
|
+ m.NbrList(nlst, d-1, periodic);
|
|
|
+ parent_mid_set[d-1].insert(nlst.begin(), nlst.end());
|
|
|
+ parent_mid.PushBack(m);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Vector<Morton<DIM>> parent_mid_sorted;
|
|
|
+ { // sort and repartition
|
|
|
+ comm.HyperQuickSort(parent_mid, parent_mid_sorted);
|
|
|
+ comm.PartitionS(parent_mid_sorted, mins[comm.Rank()]);
|
|
|
+ }
|
|
|
+
|
|
|
+ Vector<Morton<DIM>> tmp_mid;
|
|
|
+ { // add children
|
|
|
+ Vector<Morton<DIM>> clst;
|
|
|
+ tmp_mid.PushBack(Morton<DIM>()); // include root node
|
|
|
+ for (Long i = 0; i < parent_mid_sorted.Dim(); i++) {
|
|
|
+ if (i+1 == parent_mid_sorted.Dim() || parent_mid_sorted[i] != parent_mid_sorted[i+1]) {
|
|
|
+ const auto& m = parent_mid_sorted[i];
|
|
|
+ tmp_mid.PushBack(m);
|
|
|
+ m.Children(clst);
|
|
|
+ for (const auto& c : clst) tmp_mid.PushBack(c);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ auto insert_ancestor_children = [](Vector<Morton<DIM>>& mvec, const Morton<DIM>& m0) {
|
|
|
+ Integer d0 = m0.Depth();
|
|
|
+ Vector<Morton<DIM>> clst;
|
|
|
+ for (Integer d = 0; d < d0; d++) {
|
|
|
+ m0.Ancestor(d).Children(clst);
|
|
|
+ for (const auto& m : clst) mvec.PushBack(m);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ insert_ancestor_children(tmp_mid, mins[rank]);
|
|
|
+ omp_par::merge_sort(tmp_mid.begin(), tmp_mid.end());
|
|
|
+ }
|
|
|
+
|
|
|
+ node_mid.ReInit(0);
|
|
|
+ for (Long i = 0; i < tmp_mid.Dim(); i++) { // remove duplicates
|
|
|
+ if (i+1 == tmp_mid.Dim() || tmp_mid[i] != tmp_mid[i+1]) {
|
|
|
+ node_mid.PushBack(tmp_mid[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
{ // Set node_mid, node_attr
|
|
|
Morton<DIM> m0 = (rank ? mins[rank] : Morton<DIM>() );
|
|
|
Morton<DIM> m1 = (rank+1<np ? mins[rank+1] : Morton<DIM>().Next());
|
|
|
Long Nnodes = node_mid.Dim();
|
|
|
node_attr.ReInit(Nnodes);
|
|
|
for (Long i = 0; i < Nnodes; i++) {
|
|
|
- node_attr[i].Leaf = 1;
|
|
|
+ node_attr[i].Leaf = !(i+1<Nnodes && node_mid[i].isAncestor(node_mid[i+1]));
|
|
|
node_attr[i].Ghost = (node_mid[i] < m0 || node_mid[i] >= m1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- { // Add non-leaf nodes and place-holder for ghost nodes
|
|
|
+ { // Add place-holder for ghost nodes
|
|
|
// TODO
|
|
|
}
|
|
|
{ // Update node_data, node_cnt
|
|
@@ -348,6 +406,24 @@ template <class Real, Integer DIM> class Tree {
|
|
|
|
|
|
comm.PartitionS(node_mid_orig, mins[comm.Rank()]);
|
|
|
|
|
|
+ Vector<Long> new_cnt_range0(node_mid.Dim()), new_cnt_range1(node_mid.Dim());
|
|
|
+ { // Set new_cnt_range0, new_cnt_range1
|
|
|
+ for (Long i = 0; i < start_idx; i++) {
|
|
|
+ new_cnt_range0[i] = 0;
|
|
|
+ new_cnt_range1[i] = 0;
|
|
|
+ }
|
|
|
+ for (Long i = start_idx; i < end_idx; i++) {
|
|
|
+ auto m0 = (node_mid[i+0]);
|
|
|
+ auto m1 = (i+1==end_idx ? Morton<DIM>().Next() : (node_mid[i+1]));
|
|
|
+ new_cnt_range0[i] = std::lower_bound(node_mid_orig.begin(), node_mid_orig.begin() + node_mid_orig.Dim(), m0) - node_mid_orig.begin();
|
|
|
+ new_cnt_range1[i] = std::lower_bound(node_mid_orig.begin(), node_mid_orig.begin() + node_mid_orig.Dim(), m1) - node_mid_orig.begin();
|
|
|
+ }
|
|
|
+ for (Long i = end_idx; i < node_mid.Dim(); i++) {
|
|
|
+ new_cnt_range0[i] = 0;
|
|
|
+ new_cnt_range1[i] = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
Vector<Long> cnt_tmp;
|
|
|
Vector<Real> data_tmp;
|
|
|
for (const auto& pair : node_data) {
|
|
@@ -375,21 +451,12 @@ template <class Real, Integer DIM> class Tree {
|
|
|
comm.PartitionN(cnt_tmp, node_mid_orig.Dim());
|
|
|
|
|
|
cnt_->ReInit(node_mid.Dim());
|
|
|
- for (Long i = 0; i < start_idx; i++) {
|
|
|
- cnt_[0][i] = 0;
|
|
|
- }
|
|
|
- for (Long i = start_idx; i < end_idx; i++) {
|
|
|
- auto m0 = coarsest_ancestor_mid(node_mid[i+0]);
|
|
|
- auto m1 = (i+1==end_idx ? Morton<DIM>().Next() : coarsest_ancestor_mid(node_mid[i+1]));
|
|
|
- Long a = std::lower_bound(node_mid_orig.begin(), node_mid_orig.begin() + node_mid_orig.Dim(), m0) - node_mid_orig.begin();
|
|
|
- Long b = std::lower_bound(node_mid_orig.begin(), node_mid_orig.begin() + node_mid_orig.Dim(), m1) - node_mid_orig.begin();
|
|
|
- // TODO: precompute a and b
|
|
|
-
|
|
|
- cnt_[0][i] = 0;
|
|
|
- for (Long j = a; j < b; j++) cnt_[0][i] += cnt_tmp[j];
|
|
|
- }
|
|
|
- for (Long i = end_idx; i < node_mid.Dim(); i++) {
|
|
|
- cnt_[0][i] = 0;
|
|
|
+ for (Long i = 0; i < node_mid.Dim(); i++) {
|
|
|
+ Long sum = 0;
|
|
|
+ Long j0 = new_cnt_range0[i];
|
|
|
+ Long j1 = new_cnt_range1[i];
|
|
|
+ for (Long j = j0; j < j1; j++) sum += cnt_tmp[j];
|
|
|
+ cnt_[0][i] = sum;
|
|
|
}
|
|
|
SCTL_ASSERT(omp_par::reduce(cnt_->begin(), cnt_->Dim()) == omp_par::reduce(cnt_tmp.begin(), cnt_tmp.Dim()));
|
|
|
|
|
@@ -499,7 +566,7 @@ template <class Real, Integer DIM> class Tree {
|
|
|
|
|
|
static void scan(Vector<Long>& dsp, const Vector<Long>& cnt) {
|
|
|
dsp.ReInit(cnt.Dim());
|
|
|
- dsp[0] = 0;
|
|
|
+ if (cnt.Dim()) dsp[0] = 0;
|
|
|
omp_par::scan(cnt.begin(), dsp.begin(), cnt.Dim());
|
|
|
}
|
|
|
|
|
@@ -537,9 +604,9 @@ template <class Real, Integer DIM, class BaseTree = Tree<Real,DIM>> class PtTree
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
- void UpdateRefinement(const Vector<Real>& coord, Long M = 1) {
|
|
|
+ void UpdateRefinement(const Vector<Real>& coord, Long M = 1, bool balance21 = 0, bool periodic = 0) {
|
|
|
const auto& comm = this->GetComm();
|
|
|
- BaseTree::UpdateRefinement(coord, M);
|
|
|
+ BaseTree::UpdateRefinement(coord, M, balance21, periodic);
|
|
|
|
|
|
Long start_node_idx, end_node_idx;
|
|
|
{ // Set start_node_idx, end_node_idx
|