#ifndef _SCTL_TREE_ #define _SCTL_TREE_ #include #include SCTL_INCLUDE(comm.hpp) #include SCTL_INCLUDE(morton.hpp) #include SCTL_INCLUDE(vtudata.hpp) #include SCTL_INCLUDE(ompUtils.hpp) #include #include #include namespace SCTL_NAMESPACE { template class Tree { public: struct NodeAttr { unsigned char Leaf : 1, Ghost : 1; }; struct NodeLists { Long p2n; Long parent; Long child[1 << DIM]; Long nbr[sctl::pow(3)]; }; static constexpr Integer Dim(); Tree(const Comm& comm_ = Comm::Self()); ~Tree(); const Vector>& GetPartitionMID() const; const Vector>& GetNodeMID() const; const Vector& GetNodeAttr() const; const Vector& GetNodeLists() const; const Comm& GetComm() const; template void UpdateRefinement(const Vector& coord, Long M = 1, bool balance21 = 0, bool periodic = 0); template void AddData(const std::string& name, const Vector& data, const Vector& cnt); template void GetData(Vector& data, Vector& cnt, const std::string& name) const; template void ReduceBroadcast(const std::string& name); template void Broadcast(const std::string& name); void DeleteData(const std::string& name); void WriteTreeVTK(std::string fname, bool show_ghost = false) const; protected: void GetData_(Iterator>& data, Iterator>& cnt, const std::string& name); static void scan(Vector& dsp, const Vector& cnt); template struct SortPair { int operator<(const SortPair &p1) const { return key < p1.key; } A key; B data; }; private: Vector> mins; Vector> node_mid; Vector node_attr; Vector node_lst; std::map> node_data; std::map> node_cnt; Vector> user_mid; Vector user_cnt; Comm comm; }; template > class PtTree : public BaseTree { public: PtTree(const Comm& comm = Comm::Self()); ~PtTree(); void UpdateRefinement(const Vector& coord, Long M = 1, bool balance21 = 0, bool periodic = 0); void AddParticles(const std::string& name, const Vector& coord); void AddParticleData(const std::string& data_name, const std::string& particle_name, const Vector& data); void GetParticleData(Vector& data, const std::string& data_name) const; void DeleteParticleData(const std::string& data_name); void WriteParticleVTK(std::string fname, std::string data_name, bool show_ghost = false) const; static void test() { Long N = 100000; Vector X(N*DIM), f(N); for (Long i = 0; i < N; i++) { // Set coordinates (X), and values (f) f[i] = 0; for (Integer k = 0; k < DIM; k++) { X[i*DIM+k] = pow<3>(drand48()*2-1.0)*0.5+0.5; f[i] += X[i*DIM+k]*k; } } PtTree tree; tree.AddParticles("pt", X); tree.AddParticleData("pt-value", "pt", f); tree.UpdateRefinement(X, 1000); // refine tree with max 1000 points per box. { // manipulate tree node data const auto& node_lst = tree.GetNodeLists(); // Get interaction lists //const auto& node_mid = tree.GetNodeMID(); //const auto& node_attr = tree.GetNodeAttr(); // get point values and count for each node Vector value; Vector cnt, dsp; tree.GetData(value, cnt, "pt-value"); // compute the dsp (the point offset) for each node dsp.ReInit(cnt.Dim()); dsp = 0; omp_par::scan(cnt.begin(), dsp.begin(), cnt.Dim()); Long node_idx = 0; for (Long i = 0; i < cnt.Dim(); i++) { // find the tree node with maximum points if (cnt[node_idx] < cnt[i]) node_idx = i; } for (Long j = 0; j < cnt[node_idx]; j++) { // for this node, set all pt-value to -1 value[dsp[node_idx]+j] = -1; } for (const Long nbr_idx : node_lst[node_idx].nbr) { // loop over the neighbors and set pt-value to 2 if (nbr_idx >= 0 && nbr_idx != node_idx) { for (Long j = 0; j < cnt[nbr_idx]; j++) { value[dsp[nbr_idx]+j] = 2; } } } } // Generate visualization tree.WriteParticleVTK("pt", "pt-value"); tree.WriteTreeVTK("tree"); } private: std::map Nlocal; std::map>> pt_mid; std::map> scatter_idx; std::map data_pt_name; }; } #include SCTL_INCLUDE(tree.txx) #endif //_SCTL_TREE_