Commit 2f2aa5a2 authored by Quentin Khan's avatar Quentin Khan

Add FTree class, the adaptive FMM tree

parent e47e97ad
#ifndef SCALFMM_TREE_HPP_
#define SCALFMM_TREE_HPP_
#include <unordered_set>
#include "FBox.hpp"
#include "FNode.hpp"
#include "FNodeIteratorBox.hpp"
#include "FInOrderNodeIterator.hpp"
#include "FPrePostOrderNodeIterator.hpp"
template<
class _ParticleContainer,
class _NodeData >
class FTree {
public:
using node_t = FNode<FTree, _ParticleContainer, _NodeData> ;
using particle_container_t = typename _ParticleContainer::value_type;
using particle_t = typename _ParticleContainer::value_type;
using Real = typename particle_t::Real;
constexpr static std::size_t Dim = particle_t::Dim;
using position_t = typename particle_t::position_t;
using box_t = FBox<position_t>;
using leaf_list_t = std::unordered_set<node_t*>;
using in_order_walk_t = FNodeIteratorBox<node_t, FInOrderNodeIterator>;
using pre_order_walk_t = FNodeIteratorBox<node_t, FPreOrderNodeIterator>;
using post_order_walk_t = FNodeIteratorBox<node_t, FPostOrderNodeIterator>;
private:
std::size_t _max_height = 50;
std::size_t _leaf_max_particle_count = 50;
box_t _box;
node_t* _root = nullptr;
leaf_list_t _leaves;
public:
void swap(FTree& tree) {
using std::swap;
swap(_max_height, tree._max_height);
swap(_box, tree._box);
swap(_root, tree._root);
swap(_leaves, tree._leaves);
swap(_leaf_max_particle_count, tree._leaf_max_particle_count);
if(tree.root() && root()) {
tree.root()->setTree(&(root()->getTree()));
}
if(root()) {
root()->setTree(this);
}
}
FTree(box_t box_) : _box(box_) {
_root = new node_t(this);
}
FTree(FTree&) = delete;
FTree(FTree&& tree) {
swap(tree);
}
FTree& operator=(FTree&) = delete;
FTree& operator=(FTree&& tree) {
swap(tree);
}
~FTree() {
delete _root;
}
std::size_t max_height() const {
return _max_height;
}
void max_height(const std::size_t& height) {
_max_height = height;
}
std::size_t leaf_max_particle_count() const {
return _leaf_max_particle_count;
}
void leaf_max_particle_count(std::size_t count) {
_leaf_max_particle_count = count;
}
node_t* root() {
return _root;
}
const node_t* root() const {
return _root;
}
const box_t& box() const {
return _box;
}
leaf_list_t& leaves() {
return _leaves;
}
const leaf_list_t& leaves() const {
return _leaves;
}
in_order_walk_t in_order_walk() {
return in_order_walk_t(root());
}
pre_order_walk_t pre_order_walk() {
return pre_order_walk_t(root());
}
post_order_walk_t post_order_walk() {
return post_order_walk_t(root());
}
void insert(particle_t p) {
root()->insert(p);
}
void extract(const particle_t& p) {
root()->extract(p);
}
void reshape() {
root()->reshape();
}
bool operator==(const FTree& other) {
return this == &other;
}
bool operator!=(const FTree& other) {
return ! (*this == other);
}
};
#endif
#include <cassert>
#include "test_Abstract.hpp"
#include "MockParticle.hpp"
#include "Adaptive/new/FNode.hpp"
#include "Adaptive/new/FTree.hpp"
#define BOX_SIDE_LEN 100
namespace scalfmm {
namespace tests {
class test_Tree : public test_Abstract<test_Tree> {
using Real = double;
constexpr static std::size_t Dim = 3;
using particle_t = MockParticle<Real, Dim>;
using particle_container_t = std::vector<particle_t>;
using tree_t = FTree<particle_container_t, NodeEmptyData>;
using node_t = typename tree_t::node_t;
using box_t = typename tree_t::box_t;
using position_t = typename box_t::position_t;
box_t box {position_t(), 100};
tree_t* tree = nullptr;
public:
void run_all() {
RUN(test_constructor);
RUN(test_swap);
RUN(test_constructor_move);
}
void set_up() {
assert(tree == nullptr);
this->tree = new tree_t(box);
}
void tear_down() {
delete this->tree;
this->tree = nullptr;
}
void test_constructor() {
assert(tree->root() != nullptr);
}
void test_swap() {
box_t t_box = {position_t(), 50};
tree_t t(t_box);
auto root = tree->root();
auto t_root = t.root();
auto leaves = tree->leaves();
auto t_leaves = t.leaves();
auto max_height = tree->max_height();
auto t_max_height = t.max_height();
auto leaf_max_particle_count = tree->leaf_max_particle_count();
auto t_leaf_max_particle_count = t.leaf_max_particle_count();
t.swap(*tree);
assert(tree->box() == t_box);
assert(tree->root() == t_root);
assert(tree->leaves() == t_leaves);
assert(tree->max_height() == t_max_height);
assert(tree->leaf_max_particle_count() == t_leaf_max_particle_count);
assert(tree->root()->getTree() == *tree);
assert(t.box() == box);
assert(t.root() == root);
assert(t.leaves() == leaves);
assert(t.max_height() == max_height);
assert(t.leaf_max_particle_count() == leaf_max_particle_count);
assert(t.root()->getTree() == t);
}
void test_constructor_move() {
auto root = tree->root();
auto leaves = tree->leaves();
auto max_height = tree->max_height();
auto leaf_max_particle_count = tree->leaf_max_particle_count();
tree_t t(std::move(*tree));
assert(t.box() == box );
assert(t.root() == root );
assert(t.leaves() == leaves );
assert(t.max_height() == max_height);
assert(t.leaf_max_particle_count() == leaf_max_particle_count);
tree_t s {tree_t(box)};
}
};
}
}
int main() {
scalfmm::tests::test_Tree().run_all();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment