diff --git a/Src/Adaptive/new/FNode.hpp b/Src/Adaptive/new/FNode.hpp
index 560ed577ea3e89e91504ddd061b90e48557e7b40..3b966ea8666b27b523d97ac9105697d605a234b3 100644
--- a/Src/Adaptive/new/FNode.hpp
+++ b/Src/Adaptive/new/FNode.hpp
@@ -691,12 +691,11 @@ private:
 
     /** Allocates this node's children */
     void create_children() {
-        using uninit_FNode = typename std::aligned_storage<sizeof(FNode)>::type;
         std::size_t idx = 0;
         // Remove this node from tree leaf list
         getTree().leaves().erase(this);
         // Create the children, add them to tree leaf list
-        FNode* tmp = reinterpret_cast<FNode*>(new uninit_FNode[child_count]);
+        FNode* tmp = this->getTree().node_memory_manager.provide(this->getDepth()+1, child_count);
         for(FNode*& child : getChildren()) {
             child = new(tmp+idx) FNode(*this, idx);
             getTree().leaves().insert(child);
@@ -710,7 +709,6 @@ private:
 
     /* Deletes this node's children */
     void delete_children() {
-        using uninit_FNode = typename std::aligned_storage<sizeof(FNode)>::type;
         // Remove children from tree leaf list, free them
         for(FNode*& child : getChildren()) {
             if(child) {
@@ -718,7 +716,6 @@ private:
                 child->~FNode();
             }
         }
-        delete[] reinterpret_cast<uninit_FNode*>(getChild(0));
         std::fill_n(this->getChildren().data(), child_count, nullptr);
         // Insert this node in tree leaf list
         getTree().leaves().insert(this);
diff --git a/Src/Adaptive/new/FTree.hpp b/Src/Adaptive/new/FTree.hpp
index 2102cebfb4c8723f2dfab1326a5cadfdd1f337ed..7814e8411711a29df367e37bd007f9cc0601a7fe 100644
--- a/Src/Adaptive/new/FTree.hpp
+++ b/Src/Adaptive/new/FTree.hpp
@@ -9,6 +9,7 @@
 #include "FNodeIteratorBox.hpp"
 #include "FInOrderNodeIterator.hpp"
 #include "FPrePostOrderNodeIterator.hpp"
+#include "UninitNodeMemoryManager.hpp"
 
 /** \brief Adaptive FMM tree
  *
@@ -72,10 +73,13 @@ private:
     /// Tree height
     std::size_t _height = 0;
 
+    UninitNodeMemoryManager<node_t> node_memory_manager;
+
 public:
     /** \brief Swaps two trees */
     void swap(FTree& tree) {
         using std::swap;
+        swap(node_memory_manager, tree.node_memory_manager);
         swap(_max_height, tree._max_height);
         swap(_box, tree._box);
         swap(_root, tree._root);
@@ -96,7 +100,8 @@ public:
      *
      */
     FTree(box_t box_) : _box(box_) {
-        _root = new node_t(this);
+        _root = this->node_memory_manager.provide(0,1);
+        new(this->_root) node_t(this);
     }
 
     FTree(FTree&) = delete;
@@ -115,7 +120,7 @@ public:
 
     /** \brief Destructor */
     ~FTree() {
-        delete _root;
+        _root->~node_t();
     }
 
     /** \brief Tree height
diff --git a/Src/Adaptive/new/UninitNodeMemoryManager.hpp b/Src/Adaptive/new/UninitNodeMemoryManager.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..781cea2abef8e97bb6f053a5d97fc52d672b918a
--- /dev/null
+++ b/Src/Adaptive/new/UninitNodeMemoryManager.hpp
@@ -0,0 +1,99 @@
+
+#ifndef UNINITNODEMEMORYMANAGER_HPP
+#define UNINITNODEMEMORYMANAGER_HPP
+
+#include <functional>
+#include <list>
+#include <vector>
+
+#include "UninitialisedMemoryProvider.hpp"
+
+/**
+ * \brief Manages uninitialised memory for nodes
+ *
+ * This class' intent is to provide block memory management for nodes. This
+ * reduces the amount of memory allocations.
+ *
+ * The nodes' memory is handled per level. Memory for a level is not garanteed
+ * to be contiguous, it is however contiguous by block.
+ *
+ * The memory requests are forwarded to UninitialisedMemoryProvider objects. A
+ * vector of list of providers is kept to ensure constant access to a level. The
+ * lists allow constant access to their last provider and allow adding new ones
+ * without reallocating the entire list.
+ *
+ * Memory is alway requested from the last provider in a list. When the last
+ * provider does not have enough memory available, a new one is appended to the
+ * list.
+ *
+ * \tparam _Node Node type
+ */
+template<class _Node>
+class UninitNodeMemoryManager {
+    /**
+     * \brief Policy for memory provider capacity
+     *
+     * \param level Level of the nodes in the tree
+     * \param count Node count
+     *
+     * \return The provider size
+     */
+    std::function<std::size_t(std::size_t level, std::size_t count)>
+    provider_size_policy = [](const std::size_t level, const std::size_t count) {
+        enum {max_level = 4};
+        return std::max(std::size_t(1) << 3*(level > max_level ? max_level : level), count);
+    };
+
+    /**
+     * \brief memory provider lists
+     *
+     * The vector allows constant access to any level, the lists allow constant
+     * access to the last element.
+     */
+    std::vector<std::list<UninitialisedMemoryProvider<_Node>>> providers;
+
+    /**
+     * \brief Fill the providers vector until given level is reached
+     *
+     * \param level Tree level
+     */
+    void add_until_level(const std::size_t level) noexcept {
+        const std::size_t provider_count = this->providers.size();
+        if(level < provider_count) {
+            return;
+        }
+        this->providers.resize(level+1);
+        for(std::size_t l = provider_count; l < level+1; ++l) {
+            this->providers[l].emplace_back(provider_size_policy(level, 0));
+        }
+    }
+
+public:
+
+    /**
+     * \brief Provide uninitialised memory for given node count and tree level
+     *
+     * \param level Node level in the tree
+     * \param count Node count
+     *
+     * \return A pointer to the first node. Memory is uninitialised.
+     */
+    _Node* provide(const std::size_t level, const std::size_t count) noexcept {
+        // Check that a provider for given level exists
+        if(this->providers.size() < level+1) {
+            this->add_until_level(level+1);
+        }
+
+        // Add a provider when needed
+        if(! this->providers[level].back().can_provide(count)) {
+            this->providers[level].emplace_back(provider_size_policy(level, count));
+        }
+
+        return this->providers[level].back().provide(count);
+    }
+
+
+};
+
+
+#endif /* UNINITNODEMEMORYMANAGER_HPP */
diff --git a/Src/Adaptive/new/UninitialisedMemoryProvider.hpp b/Src/Adaptive/new/UninitialisedMemoryProvider.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..23ca1e3e12483cc35c1cc341bccfcc3cca0978fb
--- /dev/null
+++ b/Src/Adaptive/new/UninitialisedMemoryProvider.hpp
@@ -0,0 +1,135 @@
+
+#ifndef UNINITIALISEDMEMORYPROVIDER_HPP
+#define UNINITIALISEDMEMORYPROVIDER_HPP
+
+#include <cmath>
+#include <memory>
+#include <sstream>
+
+/**
+ * \brief Basic item provider
+ *
+ * A basic uninitialised memory provider. Provides heap allocation of a constant
+ * size array of objects. No reallocation/release can happen apart from deleting
+ * the provider.
+ *
+ * \tparam T Type of the object to provide memory for
+ */
+template<class T>
+class UninitialisedMemoryProvider {
+public:
+    using type = T;
+
+private:
+    using uninit_item = typename std::aligned_storage<sizeof(T)>::type;
+    const std::size_t _capacity = 1<<3;
+    std::size_t _size = 0;
+    std::unique_ptr<uninit_item[]> _data =
+        std::unique_ptr<uninit_item[]>{new uninit_item[this->_capacity]};
+
+    std::size_t& size() noexcept {
+        return this->_size;
+    }
+
+    /**
+     * \brief Accessor to the underlying data
+     */
+    type* data() noexcept {
+        return reinterpret_cast<type*>(this->_data.get());
+    }
+
+public:
+    UninitialisedMemoryProvider() = delete;
+    UninitialisedMemoryProvider(const UninitialisedMemoryProvider&) = delete;
+    UninitialisedMemoryProvider& operator=(const UninitialisedMemoryProvider&) = delete;
+    UninitialisedMemoryProvider(UninitialisedMemoryProvider&&) = default;
+    UninitialisedMemoryProvider& operator=(UninitialisedMemoryProvider&&) = default;
+
+    /**
+     * \brief Create a provider that may contain count items
+     *
+     * \param count Bucket capacity
+     */
+    UninitialisedMemoryProvider(std::size_t count) : _capacity(count) {}
+
+    /**
+     * \brief Total capacity of the provider
+     */
+    std::size_t capacity() const noexcept {
+        return this->_capacity;
+    }
+
+    /**
+     * \brief Already provided object count
+     */
+    std::size_t size() const noexcept {
+        return this->_size;
+    }
+
+    /**
+     * \brief Read-only accessor to the underlying data
+     */
+    const type* data() const noexcept {
+        return reinterpret_cast<type*>(this->_data.get());
+    }
+
+    /**
+     * \brief Provide memory for given object count
+     *
+     * Checks that the provider can issue enough memory for the required object
+     * count and returns a pointer to the first one.
+     *
+     * \param count Required object count
+     *
+     * \return An array of uninitialised objects
+     *
+     * \exception std::length_error When the requested count cannot be provided
+     * (capacity - size < count)
+     */
+    type* provide(const std::size_t count) {
+        if(! this->can_provide(count)) {
+            std::stringstream sstr;
+            sstr << "Cannot provide enough items, asked for ";
+            sstr << count << ", got " << this->capacity() - this->size();
+            throw std::length_error(sstr.str());
+        }
+        return unsafe_provide(count);
+    }
+
+
+    /**
+     * \brief Checks whether the provider has enought memory left or not
+     *
+     * \param count Object count
+     *
+     * \return True if at least memory for count items is available, false
+     * otherwise.
+     */
+    bool can_provide(const std::size_t count) const noexcept {
+        return this->size() + count <= this->capacity();
+    }
+
+    /**
+     * \brief Provide memory for given object count without checks
+     *
+     * This version of the #provide method does not check nor throw in case or
+     * error, it is up to the user to ensure that enough memory is available
+     * before calling it.
+     *
+     * The provider size is updated accordinly to the request, therefore it is
+     * possible to check after the call is size <= capacity.
+     *
+     * \param count The required object count
+     *
+     * \return An array of uninitialised objects
+     */
+    type* unsafe_provide(const std::size_t count) noexcept {
+        auto ret = this->data() + this->size();
+        this->_size += count;
+        return ret;
+    }
+
+};
+
+
+#endif /* UNINITIALISEDMEMORYPROVIDER_HPP */