tree.hpp
This header file provides functionality for creating and manipulating tree data structures, particularly designed for spatial partitioning and distributed computing.
Classes and Types
-
template<Integer DIM>
class Tree Class template representing a tree data structure.
- Template Parameters:
DIM – Number of spatial dimensions.
Subclassed by sctl::PtTree< Real, DIM, BaseTree >
Structs:
NodeAttr: Struct defining attributes of tree nodes.
NodeLists: Struct defining node-lists of tree nodes.Constructors:
Tree(comm): Construct a distributed memory tree.Methods:
Dim(): Returns the number of spatial dimensions.
GetPartitionMID(): Returns the vector of Morton IDs partitioning the processor domains.
GetNodeMID(): Returns the vector of Morton IDs of tree nodes.
GetNodeAttr(): Returns the vector of attributes of tree nodes.
GetNodeLists(): Returns the vector of node-lists of tree nodes.
GetComm(): Retrieves the communicator associated with the tree.
UpdateRefinement(coord, M, balance21, periodic): Update tree refinement and repartition node data among the new tree nodes.
AddData(name, data, cnt): Add named data to the tree nodes.
GetData(data, cnt, name): Get node data.
ReduceBroadcast(name): Perform reduction operation and broadcast.
Broadcast(name): Broadcast operation.
DeleteData(name): Delete data from the tree nodes.
WriteTreeVTK(fname, show_ghost): Write VTK visualization.Usage guide: Using Tree and PtTree classes
-
template<class Real, Integer DIM, class BaseTree = Tree<DIM>>
class PtTree : public sctl::Tree<DIM> Class template representing a point tree in a specified dimension.
- Template Parameters:
Real – Data type for the coordinates and values of points.
DIM – Dimensionality of the point tree.
BaseTree – Base class for the point tree. Defaults to Tree<DIM>.
Constructors:
PtTree(comm): Construct a distributed memory particle tree.Methods:
AddParticles(name, coord): Add particles to the point tree.
AddParticleData(data_name, particle_name, data): Add particle data to the point tree.
GetParticleData(data, data_name): Get particle data from the point tree.
UpdateRefinement(coord, M, balance21, periodic): Update refinement of the point tree based on given coordinates.
DeleteParticleData(data_name): Delete particle data from the point tree.
WriteParticleVTK(fname, data_name, show_ghost): Write particle data to a VTK file.Usage guide: Using Tree and PtTree classes
/**
* @file tree.hpp
* Definition of Tree and PtTree classes.
*/
#ifndef _SCTL_TREE_HPP_
#define _SCTL_TREE_HPP_
#include <map> // for map
#include <string> // for basic_string, string
#include "sctl/common.hpp" // for Long, Integer, sctl
#include "sctl/comm.hpp" // for Comm
#include "sctl/comm.txx" // for Comm::Self
#include "sctl/math_utils.txx" // for pow
#include "sctl/vector.hpp" // for Vector
namespace sctl {
template <Integer DIM> class Morton;
/**
* Class template representing a tree data structure.
*
* @tparam DIM Number of spatial dimensions.
*/
template <Integer DIM> class Tree {
public:
/**
* Structure for storing attributes of a tree node.
*/
struct NodeAttr {
unsigned char Leaf : 1, Ghost : 1;
};
/**
* Structure for storing lists of nodes (children, parent, neighbors).
*/
struct NodeLists {
Long p2n; ///< path-to-node: id among the siblings
Long parent; ///< index of the parent node
Long child[1 << DIM]; ///< index of the children
Long nbr[sctl::pow<DIM,Integer>(3)]; ///< index of the neighbors at the same level
};
/**
* @return The number of spatial dimensions.
*/
static constexpr Integer Dim();
/**
* Constructs a Tree object.
*
* @param comm_ Communicator.
*/
Tree(const Comm& comm_ = Comm::Self());
/**
* Destroys the Tree object.
*/
~Tree();
/**
* @return Vector of Morton IDs partitioning the processor domains.
*/
const Vector<Morton<DIM>>& GetPartitionMID() const;
/**
* @return Vector of Morton IDs of tree nodes.
*/
const Vector<Morton<DIM>>& GetNodeMID() const;
/**
* @return Vector of attributes of tree nodes.
*/
const Vector<NodeAttr>& GetNodeAttr() const;
/**
* @return Vector of node-lists of tree nodes.
*/
const Vector<NodeLists>& GetNodeLists() const;
/**
* @return The communicator.
*/
const Comm& GetComm() const;
/**
* Update tree refinement and repartition node data among the new tree nodes.
*
* @param[in] coord Particle coordinates (in [0,1]^dim stored in AoS order) that describe the new tree refinement.
* @param[in] M Maximum number of particles per tree node.
* @param[in] balance21 Whether to do level-restriction (2:1 balance refinement).
* @param[in] periodicity Per-axis periodicity bitmask (e.g. `Periodicity::X | Periodicity::Y`, or `all_periodic(DIM)`).
* @param[in] halo_size 2^halo_size neighboring boxes will be included in the halo region. Default value of -1 means no halo region.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
template <class Real> void UpdateRefinement(const Vector<Real>& coord, Long M = 1, bool balance21 = 0, Periodicity periodicity = Periodicity::NONE, Integer halo_size = -1);
/**
* Add named data to the tree nodes.
*
* @param[in] name Name for the data. Must not already exist on this tree.
* @param[in] data Contiguous data for all nodes, concatenated in node
* order. Must satisfy `data.Dim() == dof * sum(cnt)` for some `dof >= 0`.
* @param[in] cnt Number of data elements per node (length = number of tree nodes).
*
* @note Collective; must be called from all processes.
*
* @warning Storage is type-erased. `GetData<U>` for this `name` only
* round-trips when `U` matches the `ValueType` used here.
*/
template <class ValueType> void AddData(const std::string& name, const Vector<ValueType>& data, const Vector<Long>& cnt);
/**
* Get node data.
*
* @param[out] data Non-owning view of the tree's internal buffer for this
* data. Must not be resized; in-place mutation aliases the stored data.
* @param[out] cnt Number of data elements per node (length = number of tree nodes). Non-owning view; must not be modified.
* @param[in] name Name of the data.
*
* @warning `ValueType` must match the type used in the corresponding
* `AddData`; otherwise the bytes are silently reinterpreted.
*/
template <class ValueType> void GetData(Vector<ValueType>& data, Vector<Long>& cnt, const std::string& name) const;
/**
* Reduce data on nodes shared between processors and then broadcast the halo/ghost node data. The resulting tree
* will have ghost nodes added to the tree.
*
* @param[in] name Name of the data.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
template <class ValueType> void ReduceBroadcast(const std::string& name);
/**
* Broadcast the halo/ghost node data. The resulting tree will have ghost nodes added to the tree.
*
* @param[in] name Name of the data.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
template <class ValueType> void Broadcast(const std::string& name);
/**
* Delete data from the tree nodes.
*
* @param[in] name Name of the data.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
void DeleteData(const std::string& name);
/**
* Write VTK visualization.
*
* @param[in] fname Filename for the output.
* @param[in] show_ghost Whether to show ghost nodes.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
void WriteTreeVTK(std::string fname, bool show_ghost = false) const;
protected:
void GetData_(Iterator<Vector<char>>& data, Iterator<Vector<Long>>& cnt, const std::string& name);
static void scan(Vector<Long>& dsp, const Vector<Long>& cnt);
template <typename A, typename B> struct SortPair {
int operator<(const SortPair<A, B> &p1) const { return key < p1.key; }
A key;
B data;
};
private:
Vector<Morton<DIM>> mins;
Vector<Morton<DIM>> node_mid;
Vector<NodeAttr> node_attr;
Vector<NodeLists> node_lst;
std::map<std::string, Vector<char>> node_data;
std::map<std::string, Vector<Long>> node_cnt;
Vector<Morton<DIM>> user_mid;
Vector<Long> user_cnt;
Comm comm;
};
/**
* Class template representing a point tree in a specified dimension.
*
* @tparam Real Data type for the coordinates and values of points.
* @tparam DIM Dimensionality of the point tree.
* @tparam BaseTree Base class for the point tree. Defaults to Tree<DIM>.
*/
template <class Real, Integer DIM, class BaseTree = Tree<DIM>> class PtTree : public BaseTree {
public:
/**
* Constructor for PtTree.
*
* @param comm Communication object for distributed computing. Defaults to Comm::Self().
*/
PtTree(const Comm& comm = Comm::Self());
/**
* Destructor for PtTree.
*/
~PtTree();
/**
* Update refinement of the point tree based on given coordinates.
*
* @param coord Coordinates of the points.
* @param M Maximum number of points per box for refinement.
* @param balance21 Flag indicating whether to construct a level-restricted
* tree with neighboring boxes within one level of each other.
* @param periodicity Per-axis periodicity bitmask (e.g. `Periodicity::X | Periodicity::Y`, or `all_periodic(DIM)`).
* @param[in] halo_size 2^halo_size neighboring boxes will be included in the halo region
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
void UpdateRefinement(const Vector<Real>& coord, Long M = 1, bool balance21 = 0, Periodicity periodicity = Periodicity::NONE, Integer halo_size = -1);
/**
* Add particles to the point tree.
*
* @param name Name of the particle group.
* @param coord Coordinates of the particles.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
void AddParticles(const std::string& name, const Vector<Real>& coord);
/**
* Add particle data to the point tree.
*
* @param data_name Name of the data. Must not already exist.
* @param particle_name Name of an existing particle group from `AddParticles`.
* @param data Local data values, sized `dof * Nlocal[particle_name]` for
* some implicit `dof`. Reordered to match the particle group.
*
* @note Collective; must be called from all processes.
*/
void AddParticleData(const std::string& data_name, const std::string& particle_name, const Vector<Real>& data);
/**
* Get particle data from the point tree. The data scattered back to
* the original ordering of the particles.
*
* @param data Vector to store the data values.
* @param data_name Name of the data.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
void GetParticleData(Vector<Real>& data, const std::string& data_name) const;
/**
* Delete particle data from the point tree.
*
* @param data_name Name of the data to delete.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
void DeleteParticleData(const std::string& data_name);
/**
* Write particle data to a VTK file.
*
* @param fname Filename for the VTK file.
* @param data_name Name of the data to write.
* @param show_ghost Flag indicating whether to include ghost particles in the visualization.
*
* @note This is a collective operation and must be called from all processes in the communicator.
*/
void WriteParticleVTK(std::string fname, std::string data_name, bool show_ghost = false) const;
/**
* Example function demonstrating usage of the PtTree class.
*
* This function creates a PtTree object, adds particles, performs tree manipulation, and generates visualization.
*/
static void test();
private:
std::map<std::string, Long> Nlocal; ///< Number of local particles for each group.
std::map<std::string, Vector<Morton<DIM>>> pt_mid; ///< Morton indices for each particle group.
std::map<std::string, Vector<Long>> scatter_idx; ///< Scatter indices for each particle group.
std::map<std::string, std::string> data_pt_name; ///< Mapping of data name to particle name.
};
}
#endif // _SCTL_TREE_HPP_