New octtree tool
This commit is contained in:
parent
9c52937c74
commit
6422e08208
@ -1,5 +1,5 @@
|
|||||||
SHLIBS= libCosmoTool.so
|
SHLIBS= libCosmoTool.so
|
||||||
SOURCES= loadRamses.cpp yorick.cpp miniargs.cpp fortran.cpp interpolate.cpp load_data.cpp powerSpectrum.cpp
|
SOURCES= loadRamses.cpp yorick.cpp miniargs.cpp fortran.cpp interpolate.cpp load_data.cpp powerSpectrum.cpp octTree.cpp
|
||||||
LIBS= -lnetcdf_c++ -lnetcdf -lgsl -lgslcblas -lm
|
LIBS= -lnetcdf_c++ -lnetcdf -lgsl -lgslcblas -lm
|
||||||
|
|
||||||
include config.mk
|
include config.mk
|
||||||
@ -8,7 +8,7 @@ VPATH=../src
|
|||||||
|
|
||||||
all: $(SHLIBS)
|
all: $(SHLIBS)
|
||||||
|
|
||||||
libCosmoTool.so: loadRamses.o yorick.o miniargs.o fortran.o interpolate.o load_data.o powerSpectrum.o
|
libCosmoTool.so: loadRamses.o yorick.o miniargs.o fortran.o interpolate.o load_data.o powerSpectrum.o octTree.o
|
||||||
|
|
||||||
depend: $(SOURCES)
|
depend: $(SOURCES)
|
||||||
@echo "[DEPENDS] $^"
|
@echo "[DEPENDS] $^"
|
||||||
|
132
src/octTree.cpp
Normal file
132
src/octTree.cpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cassert>
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "octTree.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace CosmoTool;
|
||||||
|
|
||||||
|
//#define VERBOSE
|
||||||
|
|
||||||
|
OctTree::OctTree(const FCoordinates *particles, octPtr numParticles,
|
||||||
|
uint32_t maxMeanTreeDepth, uint32_t maxAbsoluteDepth,
|
||||||
|
uint32_t threshold)
|
||||||
|
{
|
||||||
|
cout << "MeanTree=" << maxMeanTreeDepth << endl;
|
||||||
|
numCells = pow(8, maxMeanTreeDepth);
|
||||||
|
assert(numCells < invalidOctCell);
|
||||||
|
//#ifdef VERBOSE
|
||||||
|
cerr << "Allocating " << numCells << " octtree cells" << endl;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
cells = new OctCell[numCells];
|
||||||
|
Lbox = (float)(octCoordTypeNorm+1);
|
||||||
|
|
||||||
|
cells[0].numberLeaves = 0;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
cells[0].children[i] = emptyOctCell;
|
||||||
|
|
||||||
|
lastNode = 1;
|
||||||
|
this->particles = particles;
|
||||||
|
this->numParticles = numParticles;
|
||||||
|
buildTree(maxAbsoluteDepth);
|
||||||
|
//#ifdef VERBOSE
|
||||||
|
cerr << "Used " << lastNode << " cells" << endl;
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
OctTree::~OctTree()
|
||||||
|
{
|
||||||
|
delete cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OctTree::buildTree(uint32_t maxAbsoluteDepth)
|
||||||
|
{
|
||||||
|
for (octPtr i = 0; i < numParticles; i++)
|
||||||
|
{
|
||||||
|
OctCoords rootCenter = { octCoordCenter, octCoordCenter, octCoordCenter };
|
||||||
|
insertParticle(0, // root node
|
||||||
|
rootCenter,
|
||||||
|
octCoordCenter,
|
||||||
|
i,
|
||||||
|
maxAbsoluteDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OctTree::insertParticle(octPtr node,
|
||||||
|
const OctCoords& icoord,
|
||||||
|
octCoordType halfNodeLength,
|
||||||
|
octPtr particleId,
|
||||||
|
uint32_t maxAbsoluteDepth)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef VERBOSE
|
||||||
|
cout << "Entering " << node << " (" << icoord[0] << "," << icoord[1] << "," << icoord[2] << ")" << endl;
|
||||||
|
#endif
|
||||||
|
int octPos = 0;
|
||||||
|
int ipos[3] = { 0,0,0};
|
||||||
|
octPtr newNode;
|
||||||
|
OctCoords newCoord;
|
||||||
|
|
||||||
|
cells[node].numberLeaves++;
|
||||||
|
if (maxAbsoluteDepth == 0)
|
||||||
|
{
|
||||||
|
// All children must be invalid.
|
||||||
|
for (int i = 0 ; i < 8; i++)
|
||||||
|
cells[node].children[i] = invalidOctCell;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
if ((octPtr)(particles[particleId][j]*Lbox) > icoord[j])
|
||||||
|
{
|
||||||
|
octPos |= (1 << j);
|
||||||
|
ipos[j] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cells[node].children[octPos] == emptyOctCell)
|
||||||
|
{
|
||||||
|
// Put the particle there.
|
||||||
|
cells[node].children[octPos] = particleId | octParticleMarker;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is a node, explores it.
|
||||||
|
if (!(cells[node].children[octPos] & octParticleMarker))
|
||||||
|
{
|
||||||
|
assert(halfNodeLength >= 2);
|
||||||
|
// Compute coordinates
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
newCoord[j] = icoord[j]+(2*ipos[j]-1)*halfNodeLength/2;
|
||||||
|
insertParticle(cells[node].children[octPos], newCoord, halfNodeLength/2,
|
||||||
|
particleId, maxAbsoluteDepth-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have a particle there.
|
||||||
|
// Make a new node and insert the old particle into this node.
|
||||||
|
// Insert the new particle into the node also
|
||||||
|
// Finally put the node in place
|
||||||
|
|
||||||
|
newNode = lastNode++;
|
||||||
|
assert(lastNode != numCells);
|
||||||
|
|
||||||
|
for (int j = 0; j < 8; j++)
|
||||||
|
cells[newNode].children[j] = emptyOctCell;
|
||||||
|
cells[newNode].numberLeaves = 0;
|
||||||
|
|
||||||
|
// Compute coordinates
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
newCoord[j] = icoord[j]+(2*ipos[j]-1)*halfNodeLength/2;
|
||||||
|
|
||||||
|
octPtr oldPartId = cells[node].children[octPos] & octParticleMask;
|
||||||
|
|
||||||
|
insertParticle(newNode, newCoord, halfNodeLength/2,
|
||||||
|
oldPartId, maxAbsoluteDepth-1);
|
||||||
|
insertParticle(newNode, newCoord, halfNodeLength/2,
|
||||||
|
particleId, maxAbsoluteDepth-1);
|
||||||
|
cells[node].children[octPos] = newNode;
|
||||||
|
}
|
113
src/octTree.hpp
Normal file
113
src/octTree.hpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#ifndef __COSMOTOOL_AMR_HPP
|
||||||
|
#define __COSMOTOOL_AMR_HPP
|
||||||
|
|
||||||
|
#include "config.hpp"
|
||||||
|
|
||||||
|
namespace CosmoTool
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef uint32_t octPtr;
|
||||||
|
typedef uint16_t octCoordType;
|
||||||
|
static const uint16_t octCoordTypeNorm = 0xffff;
|
||||||
|
static const uint16_t octCoordCenter = 0x8000;
|
||||||
|
|
||||||
|
// This is also the root cell, but this one
|
||||||
|
// is never referenced (really ??).
|
||||||
|
static const octPtr invalidOctCell = 0xffffffff;
|
||||||
|
static const octPtr emptyOctCell = 0;
|
||||||
|
static const octPtr octParticleMarker = 0x80000000;
|
||||||
|
static const octPtr octParticleMask = 0x7fffffff;
|
||||||
|
|
||||||
|
typedef octCoordType OctCoords[3];
|
||||||
|
|
||||||
|
struct OctCell
|
||||||
|
{
|
||||||
|
octPtr numberLeaves;
|
||||||
|
octPtr children[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
class OctTree
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Coordinates of particles must be in the [0:1] range
|
||||||
|
OctTree(const FCoordinates *particles, octPtr numParticles,
|
||||||
|
uint32_t maxTreeDepth, uint32_t maxAbsoluteDepth,
|
||||||
|
uint32_t threshold = 1);
|
||||||
|
~OctTree();
|
||||||
|
|
||||||
|
void buildTree(uint32_t maxAbsoluteDepth);
|
||||||
|
void insertParticle(octPtr node,
|
||||||
|
const OctCoords& icoord,
|
||||||
|
octCoordType halfNodeLength,
|
||||||
|
octPtr particleId,
|
||||||
|
uint32_t maxAbsoluteDepth);
|
||||||
|
|
||||||
|
|
||||||
|
octPtr getNumberLeaves() const {
|
||||||
|
return cells[0].numberLeaves;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FunT>
|
||||||
|
void walkTree(FunT f)
|
||||||
|
{
|
||||||
|
OctCoords rootCenter = { octCoordCenter, octCoordCenter, octCoordCenter };
|
||||||
|
|
||||||
|
walkTreeElements(f, 0, rootCenter, octCoordCenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const FCoordinates *particles;
|
||||||
|
octPtr numParticles;
|
||||||
|
OctCell *cells;
|
||||||
|
float Lbox;
|
||||||
|
octPtr lastNode;
|
||||||
|
octPtr numCells;
|
||||||
|
|
||||||
|
|
||||||
|
template<typename FunT>
|
||||||
|
void walkTreeElements(FunT f, octPtr node,
|
||||||
|
const OctCoords& icoord,
|
||||||
|
octCoordType halfNodeLength)
|
||||||
|
{
|
||||||
|
OctCoords newCoord;
|
||||||
|
FCoordinates realCenter;
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
realCenter[j] = icoord[j]/(2.*octCoordCenter);
|
||||||
|
|
||||||
|
f(realCenter, cells[node].numberLeaves, halfNodeLength/(float)octCoordCenter,
|
||||||
|
cells[node].children[0] == invalidOctCell, // True if this is a meta-node
|
||||||
|
false);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
octPtr newNode = cells[node].children[i];
|
||||||
|
int ipos[3] = { (i&1), (i&2)>>1, (i&4)>>2 };
|
||||||
|
|
||||||
|
if (newNode == emptyOctCell || newNode == invalidOctCell)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
newCoord[j] = icoord[j]+(2*ipos[j]-1)*halfNodeLength/2;
|
||||||
|
|
||||||
|
if (newNode & octParticleMarker)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
realCenter[j] = newCoord[j]/(2.*octCoordCenter);
|
||||||
|
|
||||||
|
f(realCenter,
|
||||||
|
1, halfNodeLength/(2.*octCoordCenter),
|
||||||
|
false, true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
walkTreeElements(f, cells[node].children[i], newCoord, halfNodeLength/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user