Skip to content

Commit c17e9ff

Browse files
Merge pull request #9 from TimGoTheCreator/unique-pt
Update to unique pointers
2 parents 8c96725 + ca71eec commit c17e9ff

2 files changed

Lines changed: 51 additions & 49 deletions

File tree

src/gravity/octree.h

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "../struct/particle.h"
1414
#include <vector>
1515
#include <cmath>
16+
#include <memory> // Required for unique_ptr
1617
#include "dt/softening.h"
1718
#include "floatdef.h"
1819

@@ -22,35 +23,50 @@ struct Octree {
2223
real x, y, z; // node center
2324
real size; // half-width
2425
bool leaf = true;
25-
Particle* body = nullptr;
26-
Octree* child[8] = { nullptr };
26+
Particle* body = nullptr;
27+
28+
// Ownership: unique_ptr handles memory automatically
29+
std::unique_ptr<Octree> child[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
2730

2831
// Quadrupole tensor
2932
real Qxx = 0, Qyy = 0, Qzz = 0;
3033
real Qxy = 0, Qxz = 0, Qyz = 0;
3134

3235
Octree(real X, real Y, real Z, real S) : x(X), y(Y), z(Z), size(S), m(0), cx(0), cy(0), cz(0) {}
3336

34-
~Octree() { for (auto c : child) delete c; }
37+
// Destructor is now empty; unique_ptr cleans up children automatically
38+
~Octree() = default;
3539

3640
int index(const Particle& p) const {
3741
return (p.x > x) * 1 + (p.y > y) * 2 + (p.z > z) * 4;
3842
}
3943

40-
Octree* createChild(int idx) {
44+
// Returns unique_ptr to take ownership
45+
std::unique_ptr<Octree> createChild(int idx) {
4146
real hs = size * real(0.5);
42-
return new Octree(x + ((idx & 1) ? hs : -hs), y + ((idx & 2) ? hs : -hs), z + ((idx & 4) ? hs : -hs), hs);
47+
return std::make_unique<Octree>(
48+
x + ((idx & 1) ? hs : -hs),
49+
y + ((idx & 2) ? hs : -hs),
50+
z + ((idx & 4) ? hs : -hs),
51+
hs
52+
);
4353
}
4454

4555
void insert(Particle* p) {
46-
if (leaf && body == nullptr) { body = p; return; }
56+
if (leaf && body == nullptr) {
57+
body = p;
58+
return;
59+
}
60+
4761
if (leaf) {
4862
leaf = false;
49-
Particle* old = body; body = nullptr;
63+
Particle* old = body;
64+
body = nullptr;
5065
int idx = index(*old);
5166
if (!child[idx]) child[idx] = createChild(idx);
5267
child[idx]->insert(old);
5368
}
69+
5470
int idx = index(*p);
5571
if (!child[idx]) child[idx] = createChild(idx);
5672
child[idx]->insert(p);
@@ -65,7 +81,7 @@ struct Octree {
6581
}
6682

6783
m = 0; cx = cy = cz = 0;
68-
for (auto c : child) {
84+
for (auto& c : child) { // Use reference to unique_ptr
6985
if (!c) continue;
7086
c->computeMass();
7187
if (c->m == 0) continue;
@@ -75,10 +91,9 @@ struct Octree {
7591
if (m > 0) { cx /= m; cy /= m; cz /= m; }
7692

7793
Qxx = Qyy = Qzz = Qxy = Qxz = Qyz = 0;
78-
for (auto c : child) {
94+
for (auto& c : child) {
7995
if (!c || c->m == 0) continue;
8096
real rx = c->cx - cx; real ry = c->cy - cy; real rz = c->cz - cz;
81-
// Internal node softening to match force calculation
8297
real r2 = rx * rx + ry * ry + rz * rz + (size * size * real(0.01));
8398
real mchild = c->m;
8499
Qxx += mchild * (3 * rx * rx - r2);
@@ -91,6 +106,7 @@ struct Octree {
91106
}
92107
};
93108

109+
// Traverse using raw pointers (non-owning observer)
94110
inline void bhAccel(Octree* node, const Particle& p, real theta, real& ax, real& ay, real& az) {
95111
if (!node || node->m == 0) return;
96112
if (node->leaf && node->body == &p) return;
@@ -131,5 +147,7 @@ inline void bhAccel(Octree* node, const Particle& p, real theta, real& ax, real&
131147
return;
132148
}
133149

134-
for (auto c : node->child) if (c) bhAccel(c, p, theta, ax, ay, az);
150+
for (auto& c : node->child) {
151+
if (c) bhAccel(c.get(), p, theta, ax, ay, az); // Use .get() to pass raw pointer
152+
}
135153
}

src/gravity/step.h

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,95 +14,79 @@
1414
#include "floatdef.h"
1515
#include "octree.h"
1616
#include <vector>
17+
#include <memory>
18+
#include <algorithm>
1719

1820
inline void Step(std::vector<Particle> &p, real dt) {
19-
if (p.empty())
20-
return;
21+
if (p.empty()) return;
2122

2223
real theta = 0.5;
2324
real half = dt * real(0.5);
2425

25-
auto buildTree = [&](Octree *&root) {
26-
// Compute bounding box
26+
// Helper lambda that returns a unique_ptr
27+
auto buildTree = [&]() -> std::unique_ptr<Octree> {
2728
real minx = +1e30, miny = +1e30, minz = +1e30;
2829
real maxx = -1e30, maxy = -1e30, maxz = -1e30;
2930

30-
for (auto &a : p) {
31-
minx = std::min(minx, a.x);
32-
miny = std::min(miny, a.y);
33-
minz = std::min(minz, a.z);
34-
maxx = std::max(maxx, a.x);
35-
maxy = std::max(maxy, a.y);
36-
maxz = std::max(maxz, a.z);
31+
for (const auto &a : p) {
32+
minx = std::min(minx, a.x); miny = std::min(miny, a.y); minz = std::min(minz, a.z);
33+
maxx = std::max(maxx, a.x); maxy = std::max(maxy, a.y); maxz = std::max(maxz, a.z);
3734
}
3835

3936
real cx = (minx + maxx) * 0.5;
4037
real cy = (miny + maxy) * 0.5;
4138
real cz = (minz + maxz) * 0.5;
42-
real dx = maxx - minx;
43-
real dy = maxy - miny;
44-
real dz = maxz - minz;
39+
real size = std::max({maxx - minx, maxy - miny, maxz - minz}) * real(0.5);
4540

46-
real size = std::max(dx, std::max(dy, dz)) * real(0.5);
41+
if (size <= 0) size = 1;
4742

48-
if (size <= 0)
49-
size = 1; // safety
50-
51-
root = new Octree(cx, cy, cz, size);
43+
// Create the owned root
44+
auto root = std::make_unique<Octree>(cx, cy, cz, size);
5245

5346
for (auto &a : p)
5447
root->insert(&a);
5548

5649
root->computeMass();
50+
return root;
5751
};
5852

59-
// =========================
60-
// First Kick (dt/2)
61-
// =========================
53+
// --- First Kick (dt/2) ---
6254
{
63-
Octree *root = nullptr;
64-
buildTree(root);
55+
std::unique_ptr<Octree> root = buildTree();
6556

6657
#pragma omp parallel for schedule(static)
6758
for (int i = 0; i < (int)p.size(); i++) {
6859
real ax = 0, ay = 0, az = 0;
69-
bhAccel(root, p[i], theta, ax, ay, az);
60+
// Pass the raw pointer via .get() for the traversal
61+
bhAccel(root.get(), p[i], theta, ax, ay, az);
7062

7163
p[i].vx += ax * half;
7264
p[i].vy += ay * half;
7365
p[i].vz += az * half;
7466
}
75-
76-
delete root;
67+
// No 'delete root' needed! It happens automatically here.
7768
}
7869

79-
// =========================
80-
// Drift (dt)
81-
// =========================
70+
// --- Drift (dt) ---
8271
#pragma omp parallel for schedule(static)
8372
for (int i = 0; i < (int)p.size(); i++) {
8473
p[i].x += p[i].vx * dt;
8574
p[i].y += p[i].vy * dt;
8675
p[i].z += p[i].vz * dt;
8776
}
8877

89-
// =========================
90-
// Second Kick (dt/2)
91-
// =========================
78+
// --- Second Kick (dt/2) ---
9279
{
93-
Octree *root = nullptr;
94-
buildTree(root);
80+
std::unique_ptr<Octree> root = buildTree();
9581

9682
#pragma omp parallel for schedule(static)
9783
for (int i = 0; i < (int)p.size(); i++) {
9884
real ax = 0, ay = 0, az = 0;
99-
bhAccel(root, p[i], theta, ax, ay, az);
85+
bhAccel(root.get(), p[i], theta, ax, ay, az);
10086

10187
p[i].vx += ax * half;
10288
p[i].vy += ay * half;
10389
p[i].vz += az * half;
10490
}
105-
106-
delete root;
10791
}
10892
}

0 commit comments

Comments
 (0)