diff --git a/lib/node.cpp b/lib/node.cpp
index 89bd7c940064a9f65f6d51048bcc2e273a4371d4..e718ec47a30993fc26219dd7ffa1bdea7c310eb4 100644
--- a/lib/node.cpp
+++ b/lib/node.cpp
@@ -19,7 +19,7 @@ Node::Node() {
  */
 
 Node::Node(Node* root, Node* parent, double* masses, double* particles, unsigned nParticles, unsigned depth, 
-        double size, double center[3], std::vector<unsigned>& localParticles, unsigned nLocalParticles) {
+        double size, double center[3], List& localParticles, unsigned nLocalParticles) {
     parent_ = parent;
     particles_ = particles;
     nParticles_ = nParticles;
@@ -40,7 +40,36 @@ Node::Node(Node* root, Node* parent, double* masses, double* particles, unsigned
     // TODO
     // allocate children
     // check if child contains no particles, in that case set child to nullptr
-    // check if node is leaf
+    // check if node is leaf (it contains a single particle), in that case all children are nullptr
+    if (nLocalParticles <= 1) {
+        isLeaf_ = true;
+        for (unsigned i=0; i<8; ++i)
+            children_[i] = nullptr;
+    } else {
+        isLeaf_ = false;
+        
+        // for each local particle, determine which octant it is in
+        List* particleDivision = new List[nLocalParticles];
+        for (unsigned i=0; i<nLocalParticles; ++i) {
+            particleDivision[getOctant(localParticles_[i])].push_back(i);
+        }
+
+        // for each octant, create a child node
+        for (unsigned i=0; i<8; ++i) {
+            if (particleDivision[i].size() == 0) {
+                children_[i] = nullptr;
+            } else {
+                double childSize = size_/2;
+                double childCenter[3];
+                for (unsigned j=0; j<3; ++j) {
+                    childCenter[j] = center_[j] + (i & (1 << j) ? childSize : -childSize);
+                }
+                children_[i] = new Node(root, this, masses, particles, nParticles, depth+1, 
+                        childSize, childCenter, particleDivision[i], particleDivision[i].size());
+            }
+        }
+        delete[] particleDivision;
+    }
 }
 
 Node::~Node() {
@@ -64,29 +93,55 @@ Node& Node::operator=(const Node& other) {
     return *this;
 }
 
-void Node::update(std::vector<unsigned>& localParticles) {
+void Node::update(List& localParticles) {
     // TODO
     // update center of mass
     // maybe subdivide? 
     // update this node
     // update children
+
+    // for each local particle, determine which octant it is in
+    List* particleDivision = new List[nLocalParticles_];
+    for (unsigned i=0; i<nLocalParticles_; ++i) {
+        particleDivision[getOctant(localParticles_[i])].push_back(i);
+    }
+
     isLeaf_ = true;
     for (unsigned i=0; i<8; ++i) {
         if (children_[i] != nullptr) {
-            // children_[i]->update();
-            isLeaf_ = false;
+            // if child is not a nullptr and particleDivision[i] is empty, delete the child
+            // otherwise update the child
+            if (particleDivision[i].size() == 0) {
+                delete children_[i];
+                children_[i] = nullptr;
+            } else {
+                children_[i]->update(particleDivision[i]);
+                isLeaf_ = false;
+            }
+        } else {
+            // if child is a nullptr and particleDivision[i] is not empty, create a new child
+            if (particleDivision[i].size() != 0) {
+                double childSize = size_/2;
+                double childCenter[3];
+                for (unsigned j=0; j<3; ++j) {
+                    childCenter[j] = center_[j] + (i & (1 << j) ? childSize : -childSize);
+                }
+                children_[i] = new Node(root_, this, masses_, particles_, nParticles_, depth_+1, 
+                        childSize, childCenter, particleDivision[i], particleDivision[i].size());
+                isLeaf_ = false;
+            }
         }
     }
+
+    delete[] particleDivision;
 }
 
 double* Node::calculateForce(unsigned particle) {
     // calculate theta
-    double px = particles_[3*particle + 0];
-    double py = particles_[3*particle + 1];
-    double pz = particles_[3*particle + 2];
-    double lambda = std::sqrt((center_[0] - px)*(center_[0] - px)
-                            + (center_[1] - py)*(center_[1] - py)
-                            + (center_[2] - pz)*(center_[2] - pz));
+    double dx = center_[0] - particles_[3*particle + 0];
+    double dy = center_[1] - particles_[3*particle + 1];
+    double dz = center_[2] - particles_[3*particle + 2];
+    double lambda = std::sqrt(dx*dx + dy*dy + dz*dz);
     double theta = size_/lambda;
 
     // TODO
@@ -103,6 +158,7 @@ double* Node::calculateForce(unsigned particle) {
     } else {
         // TODO
     }
+
     return nullptr;
 }
 
@@ -113,4 +169,39 @@ void Node::calculateCenterOfMass() {
     for (unsigned i : localParticles_)
         for (unsigned j=0; j<3; ++j)
             centerOfMass_[j] += particles_[3*i + j] / nLocalParticles_;
+}
+
+unsigned Node::getOctant(unsigned particle) {
+    double px = particles_[localParticles_[0]];
+    double py = particles_[localParticles_[1]];
+    double pz = particles_[localParticles_[2]];
+    if (px < center_[0]) {
+        if (py < center_[1]) {
+            if (pz < center_[2]) {
+                return 0;
+            } else {
+                return 1;
+            }
+        } else {
+            if (pz < center_[2]) {
+                return 2;
+            } else {
+                return 3;
+            }
+        }
+    } else {
+        if (py < center_[1]) {
+            if (pz < center_[2]) {
+                return 4;
+            } else {
+                return 5;
+            }
+        } else {
+            if (pz < center_[2]) {
+                return 6;
+            } else {
+                return 7;
+            }
+        }
+    }
 }
\ No newline at end of file