|
@@ -383,6 +383,92 @@ template <class Real, Integer DIM> class Tree {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ { // Add place-holder for ghost nodes
|
|
|
+ Long start_idx, end_idx;
|
|
|
+ { // Set start_idx, end_idx
|
|
|
+ start_idx = std::lower_bound(node_mid.begin(), node_mid.end(), mins[rank]) - node_mid.begin();
|
|
|
+ end_idx = std::lower_bound(node_mid.begin(), node_mid.end(), (rank+1==np ? Morton<DIM>().Next() : mins[rank+1])) - node_mid.begin();
|
|
|
+ }
|
|
|
+ { // Set user_node_lst
|
|
|
+ Vector<SortPair<Long,Morton<DIM>>> user_node_lst;
|
|
|
+ Vector<Morton<DIM>> nlst;
|
|
|
+ std::set<Long> user_procs;
|
|
|
+ for (Long i = start_idx; i < end_idx; i++) {
|
|
|
+ Morton<DIM> m0 = node_mid[i];
|
|
|
+ Integer d0 = m0.Depth();
|
|
|
+ m0.NbrList(nlst, std::max<Integer>(d0-2,0), periodic);
|
|
|
+ user_procs.clear();
|
|
|
+ for (const auto& m : nlst) {
|
|
|
+ Morton<DIM> m_start = m.DFD();
|
|
|
+ Morton<DIM> m_end = m.Next();
|
|
|
+ Integer p_start = std::lower_bound(mins.begin(), mins.end(), m_start) - mins.begin() - 1;
|
|
|
+ Integer p_end = std::lower_bound(mins.begin(), mins.end(), m_end ) - mins.begin();
|
|
|
+ SCTL_ASSERT(0 <= p_start);
|
|
|
+ SCTL_ASSERT(p_start < p_end);
|
|
|
+ SCTL_ASSERT(p_end <= np);
|
|
|
+ for (Long p = p_start; p < p_end; p++) {
|
|
|
+ if (p != rank) user_procs.insert(p);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (const auto p : user_procs) {
|
|
|
+ SortPair<Long,Morton<DIM>> pair;
|
|
|
+ pair.key = p;
|
|
|
+ pair.data = m0;
|
|
|
+ user_node_lst.PushBack(pair);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ omp_par::merge_sort(user_node_lst.begin(), user_node_lst.end());
|
|
|
+
|
|
|
+ user_cnt.ReInit(np);
|
|
|
+ user_mid.ReInit(user_node_lst.Dim());
|
|
|
+ for (Integer i = 0; i < np; i++) {
|
|
|
+ SortPair<Long,Morton<DIM>> pair_start, pair_end;
|
|
|
+ pair_start.key = i;
|
|
|
+ pair_end.key = i+1;
|
|
|
+ Long cnt_start = std::lower_bound(user_node_lst.begin(), user_node_lst.end(), pair_start) - user_node_lst.begin();
|
|
|
+ Long cnt_end = std::lower_bound(user_node_lst.begin(), user_node_lst.end(), pair_end ) - user_node_lst.begin();
|
|
|
+ user_cnt[i] = cnt_end - cnt_start;
|
|
|
+ for (Long j = cnt_start; j < cnt_end; j++) {
|
|
|
+ user_mid[j] = user_node_lst[j].data;
|
|
|
+ }
|
|
|
+ std::sort(user_mid.begin() + cnt_start, user_mid.begin() + cnt_end);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Vector<Morton<DIM>> ghost_mid;
|
|
|
+ { // SendRecv user_node_lst
|
|
|
+ const Vector<Long> &send_cnt = user_cnt;
|
|
|
+ Vector<Long> send_dsp(np);
|
|
|
+ scan(send_dsp, send_cnt);
|
|
|
+
|
|
|
+ Vector<Long> recv_cnt(np), recv_dsp(np);
|
|
|
+ comm.Alltoall(send_cnt.begin(), 1, recv_cnt.begin(), 1);
|
|
|
+ scan(recv_dsp, recv_cnt);
|
|
|
+
|
|
|
+ const Vector<Morton<DIM>>& send_mid = user_mid;
|
|
|
+ Long Nsend = send_dsp[np-1] + send_cnt[np-1];
|
|
|
+ Long Nrecv = recv_dsp[np-1] + recv_cnt[np-1];
|
|
|
+ SCTL_ASSERT(send_mid.Dim() == Nsend);
|
|
|
+
|
|
|
+ ghost_mid.ReInit(Nrecv);
|
|
|
+ comm.Alltoallv(send_mid.begin(), send_cnt.begin(), send_dsp.begin(), ghost_mid.begin(), recv_cnt.begin(), recv_dsp.begin());
|
|
|
+ }
|
|
|
+
|
|
|
+ { // Update node_mid <-- ghost_mid + node_mid
|
|
|
+ Vector<Morton<DIM>> new_mid(end_idx-start_idx + ghost_mid.Dim());
|
|
|
+ Long Nsplit = std::lower_bound(ghost_mid.begin(), ghost_mid.end(), mins[rank]) - ghost_mid.begin();
|
|
|
+ for (Long i = 0; i < Nsplit; i++) {
|
|
|
+ new_mid[i] = ghost_mid[i];
|
|
|
+ }
|
|
|
+ for (Long i = 0; i < end_idx - start_idx; i++) {
|
|
|
+ new_mid[Nsplit + i] = node_mid[start_idx + i];
|
|
|
+ }
|
|
|
+ for (Long i = Nsplit; i < ghost_mid.Dim(); i++) {
|
|
|
+ new_mid[end_idx - start_idx + i] = ghost_mid[i];
|
|
|
+ }
|
|
|
+ node_mid.Swap(new_mid);
|
|
|
+ }
|
|
|
+ }
|
|
|
{ // 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());
|
|
@@ -393,10 +479,18 @@ template <class Real, Integer DIM> class Tree {
|
|
|
node_attr[i].Ghost = (node_mid[i] < m0 || node_mid[i] >= m1);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- { // Add place-holder for ghost nodes
|
|
|
- // TODO
|
|
|
+ { // Check tree
|
|
|
+ Morton<DIM> m0;
|
|
|
+ SCTL_ASSERT(node_mid.Dim() && m0 == node_mid[0]);
|
|
|
+ for (Long i = 1; i < node_mid.Dim(); i++) {
|
|
|
+ const auto& m = node_mid[i];
|
|
|
+ if (m0.isAncestor(m)) m0 = m0.Ancestor(m0.Depth()+1);
|
|
|
+ else m0 = m0.Next();
|
|
|
+ SCTL_ASSERT(m0 == m);
|
|
|
+ }
|
|
|
+ SCTL_ASSERT(m0.Next() == Morton<DIM>().Next());
|
|
|
}
|
|
|
+
|
|
|
{ // Update node_data, node_cnt
|
|
|
Long start_idx, end_idx;
|
|
|
{ // Set start_idx, end_idx
|
|
@@ -570,11 +664,11 @@ template <class Real, Integer DIM> class Tree {
|
|
|
omp_par::scan(cnt.begin(), dsp.begin(), cnt.Dim());
|
|
|
}
|
|
|
|
|
|
- //template <typename A, typename B> struct SortPair {
|
|
|
- // int operator<(const SortPair<A, B> &p1) const { return key < p1.key; }
|
|
|
- // A key;
|
|
|
- // B data;
|
|
|
- //};
|
|
|
+ template <typename A, typename B> struct SortPair {
|
|
|
+ int operator<(const SortPair<A, B> &p1) const { return key < p1.key; }
|
|
|
+ A key;
|
|
|
+ B data;
|
|
|
+ };
|
|
|
|
|
|
private:
|
|
|
|
|
@@ -585,6 +679,9 @@ template <class Real, Integer DIM> class Tree {
|
|
|
std::map<std::string, Vector<Real>> node_data;
|
|
|
std::map<std::string, Vector<Long>> node_cnt;
|
|
|
|
|
|
+ Vector<Morton<DIM>> user_mid;
|
|
|
+ Vector<Long> user_cnt;
|
|
|
+
|
|
|
Comm comm;
|
|
|
};
|
|
|
|