Commit 3f3686ea authored by berenger-bramas's avatar berenger-bramas

Add classes to save or load an entier tree from file.

This uses a custom format.

git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/scalfmm/scalfmm/trunk@250 2616d619-271b-44dc-8df4-d4a8f33a7222
parent ae5a6390
#ifndef FTREEIO_HPP
#define FTREEIO_HPP
#include <iostream>
#include <fstream>
/** This class proposes static methods to save and load
* a tree.
* It used binary format (so FReal must be the same!)
*
* The format is :
* [nb leaves]
* [nb particles in leaf][particles.....] ...
* [nb cells at level]
* [morton index][cell] ....
* ...
*/
class FTreeIO{
public:
/** The serializer class call a method on the particles or cells
* So they have to implement the write/read method
*/
template <class CellClass, class ParticleClass>
class Serializer {
public:
static void PutCell(std::ofstream*const stream, const CellClass*const cell) {
cell->write(stream);
}
static void PutParticles(std::ofstream*const stream, const ParticleClass* const particles, const int nbParticles) {
for( int idxParticle = 0 ; idxParticle < nbParticles ; ++idxParticle){
particles[idxParticle]->write(stream);
}
}
static void GetCell(std::ifstream*const stream, CellClass* const cell){
cell->read(stream);
}
static void GetParticles(std::ifstream*const stream, const ParticleClass* const particles, const int nbParticles){
for( int idxParticle = 0 ; idxParticle < nbParticles ; ++idxParticle){
particles[idxParticle]->read(stream);
}
}
};
/** The copier method simple copy in memory using memcpy
*/
template <class CellClass, class ParticleClass>
class Copier {
public:
static void PutCell(std::ofstream*const stream, const CellClass* const cell) {
stream->write((const char*)cell, sizeof(CellClass));
}
static void PutParticles(std::ofstream*const stream, const ParticleClass* const particles, const int nbParticles) {
stream->write((const char*)particles, nbParticles * sizeof(ParticleClass));
}
static void GetCell(std::ifstream*const stream, CellClass* const cell){
stream->read((char*)cell, sizeof(CellClass));
}
static void GetParticles(std::ifstream*const stream, const ParticleClass* const particles, const int nbParticles){
stream->read((char*)particles, nbParticles * sizeof(ParticleClass));
}
};
/** To save in memory */
template <class OctreeClass, class CellClass, class ParticleClass, class ClassProptotype >
static bool Save(const char filename[], OctreeClass& tree){
std::ofstream file(filename, std::ofstream::binary | std::ofstream::out );
if(!file.good()){
return false;
}
const size_t sizeof_freal = sizeof(FReal);
file.write((const char*)&sizeof_freal, sizeof(size_t));
const int height = tree.getHeight();
file.write((const char*)&height, sizeof(int));
const int subHeight = tree.getSubHeight();
file.write((const char*)&subHeight, sizeof(int));
const FReal width = tree.getBoxWidth();
file.write((const char*)&width, sizeof(FReal));
file.write((const char*)&tree.getBoxCenter(), sizeof(F3DPosition));
{
typename OctreeClass::Iterator octreeIterator(&tree);
int maxParticlesInLeaf = 0;
int nbLeaf = 0;
const std::ofstream::pos_type posNbLeaf = file.tellp();
file.write((const char*)&nbLeaf,sizeof(int));
file.write((const char*)&maxParticlesInLeaf,sizeof(int));
octreeIterator.gotoBottomLeft();
const bool useTargetSource = (octreeIterator.getCurrentListSrc() != octreeIterator.getCurrentListTargets());
if( useTargetSource ){
do{
const int nbParticlesInLeaf = (octreeIterator.getCurrentListSrc()->getSize() + octreeIterator.getCurrentListTargets()->getSize());
file.write((const char*)&nbParticlesInLeaf,sizeof(int));
ClassProptotype::PutParticles( &file, octreeIterator.getCurrentListSrc()->data(), octreeIterator.getCurrentListSrc()->getSize());
ClassProptotype::PutParticles( &file, octreeIterator.getCurrentListTargets()->data(), octreeIterator.getCurrentListTargets()->getSize());
++nbLeaf;
if( maxParticlesInLeaf < nbParticlesInLeaf) maxParticlesInLeaf = nbParticlesInLeaf;
} while(octreeIterator.moveRight());
}
else{
do{
const int nbParticlesInLeaf = octreeIterator.getCurrentListSrc()->getSize();
file.write((const char*)&nbParticlesInLeaf,sizeof(int));
ClassProptotype::PutParticles( &file, octreeIterator.getCurrentListSrc()->data(), octreeIterator.getCurrentListSrc()->getSize());
++nbLeaf;
if( maxParticlesInLeaf < nbParticlesInLeaf) maxParticlesInLeaf = nbParticlesInLeaf;
} while(octreeIterator.moveRight());
}
const std::ofstream::pos_type currentPos = file.tellp();
file.seekp(posNbLeaf);
file.write((const char*)&nbLeaf,sizeof(int));
file.write((const char*)&maxParticlesInLeaf,sizeof(int));
file.seekp(currentPos);
}
// Start from leal level - 1
typename OctreeClass::Iterator octreeIterator(&tree);
octreeIterator.gotoBottomLeft();
typename OctreeClass::Iterator avoidGotoLeftIterator(octreeIterator);
// for each levels
for(int idxLevel = tree.getHeight() - 1 ; idxLevel > 1 ; --idxLevel ){
int nbCells = 0;
const std::ofstream::pos_type posNbCells = file.tellp();
file.write((const char*)&nbCells,sizeof(int));
do{
const MortonIndex mindex = octreeIterator.getCurrentGlobalIndex();
file.write((const char*)&mindex,sizeof(MortonIndex));;
ClassProptotype::PutCell( &file, octreeIterator.getCurrentCell());
++nbCells;
} while(octreeIterator.moveRight());
const std::ofstream::pos_type currentPos = file.tellp();
file.seekp(posNbCells);
file.write((const char*)&nbCells,sizeof(int));
file.seekp(currentPos);
avoidGotoLeftIterator.moveUp();
octreeIterator = avoidGotoLeftIterator;// equal octreeIterator.moveUp(); octreeIterator.gotoLeft();
}
file.flush();
file.close();
return true;
}
/** To load from memory */
template <class OctreeClass, class CellClass, class ParticleClass, class ClassProptotype >
static bool Load(const char filename[], OctreeClass& tree){
std::ifstream file(filename, std::ifstream::binary | std::ifstream::in );
if(!file.good()){
return false;
}
size_t sizeof_freal = 0;
file.read((char*)&sizeof_freal, sizeof(size_t));
if( sizeof_freal != sizeof(FReal)){
std::cerr << "Error Freal do not coincide with file type:\n";
std::cerr << "In file : " << sizeof_freal << " Real : " << sizeof(FReal) << "\n";
return false;
}
int treeHeight = 0;
file.read((char*)&treeHeight, sizeof(int));
int treeSubHeight = 0;
file.read((char*)&treeSubHeight, sizeof(int));
FReal boxWidth = 0;
file.read((char*)&boxWidth, sizeof(FReal));
F3DPosition center;
file.read((char*)&center, sizeof(F3DPosition));
tree.~OctreeClass();
new (&tree) OctreeClass(treeHeight,treeSubHeight,boxWidth,center);
{
int nbLeaf = 0;
file.read((char*)&nbLeaf, sizeof(int));
int maxParticlesInLeaf = 0;
file.read((char*)&maxParticlesInLeaf, sizeof(int));
ParticleClass* const particles = new ParticleClass[maxParticlesInLeaf];
for(int idxLeaf = 0 ; idxLeaf < nbLeaf ; ++idxLeaf){
int particlesInLeaf = 0;
file.read((char*)&particlesInLeaf, sizeof(int));
ClassProptotype::GetParticles(&file, particles, particlesInLeaf);
for(int idxParticle = 0 ; idxParticle < particlesInLeaf ; ++idxParticle){
tree.insert(particles[idxParticle]);
}
}
delete[] particles;
}
// Start from leal level - 1
typename OctreeClass::Iterator octreeIterator(&tree);
octreeIterator.gotoBottomLeft();
typename OctreeClass::Iterator avoidGotoLeftIterator(octreeIterator);
// for each levels
for(int idxLevel = tree.getHeight() - 1 ; idxLevel > 1 ; --idxLevel ){
int nbCells = 0;
file.read((char*)&nbCells, sizeof(int));
do{
MortonIndex mindex;
file.read((char*)&mindex, sizeof(MortonIndex));
if(mindex != octreeIterator.getCurrentGlobalIndex()){
std::cerr << "Error indexes are different\n";
return false;
}
ClassProptotype::GetCell(&file,octreeIterator.getCurrentCell());
--nbCells;
} while(octreeIterator.moveRight());
if(nbCells != 0){
std::cerr << "Wrong number of cells at level " << idxLevel << "\n";
return false;
}
avoidGotoLeftIterator.moveUp();
octreeIterator = avoidGotoLeftIterator;
}
file.close();
return true;
}
};
#endif // FTREEIO_HPP
// /!\ Please, you must read the license at the bottom of this page
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "../Src/Utils/FTic.hpp"
#include "../Src/Utils/FParameters.hpp"
#include "../Src/Containers/FOctree.hpp"
#include "../Src/Containers/FVector.hpp"
#include "../Src/Fmb/FFmbKernels.hpp"
#include "../Src/Fmb/FFmbComponents.hpp"
#include "../Src/Files/FFmaLoader.hpp"
#include "../Src/Files/FTreeIO.hpp"
// Simply create particles and try the kernels
int main(int argc, char ** argv){
typedef FmbParticle ParticleClass;
typedef FmbCell CellClass;
typedef FVector<ParticleClass> ContainerClass;
typedef FSimpleLeaf<ParticleClass, ContainerClass > LeafClass;
typedef FOctree<ParticleClass, CellClass, ContainerClass , LeafClass > OctreeClass;
///////////////////////What we do/////////////////////////////
std::cout << ">> This executable has to be used to load or retrieve an entier tree.\n";
//////////////////////////////////////////////////////////////
const int NbLevels = FParameters::getValue(argc,argv,"-h", 9);
const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3);
FTic counter;
const char* const defaultFilename = "testLoaderFMA.fma"; //../../Data/ "testLoaderFMA.fma" "testFMAlgorithm.fma" Sphere.fma
const char* filename;
if(argc == 1){
std::cout << "You have to give a .fma file in argument.\n";
std::cout << "The program will try a default file : " << defaultFilename << "\n";
filename = defaultFilename;
}
else{
filename = argv[1];
std::cout << "Opening : " << filename << "\n";
}
FFmaLoader<ParticleClass> loader(filename);
if(!loader.isOpen()){
std::cout << "Loader Error, " << filename << " is missing\n";
return 1;
}
// -----------------------------------------------------
OctreeClass tree(NbLevels, SizeSubLevels, loader.getBoxWidth(), loader.getCenterOfBox());
// -----------------------------------------------------
std::cout << "Creating & Inserting " << loader.getNumberOfParticles() << " particles ..." << std::endl;
std::cout << "\tHeight : " << NbLevels << " \t sub-height : " << SizeSubLevels << std::endl;
counter.tic();
{
ParticleClass particleToFill;
for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
loader.fillParticle(particleToFill);
tree.insert(particleToFill);
}
}
counter.tac();
std::cout << "Done " << "(@Creating and Inserting Particles = " << counter.elapsed() << "s)." << std::endl;
// -----------------------------------------------------
std::cout << "Save tree ..." << std::endl;
FTreeIO::Save<OctreeClass, CellClass, ParticleClass, FTreeIO::Copier<CellClass, ParticleClass> >("/tmp/tree.data", tree);
// -----------------------------------------------------
std::cout << "Load tree ..." << std::endl;
FTreeIO::Load<OctreeClass, CellClass, ParticleClass, FTreeIO::Copier<CellClass, ParticleClass> >("/tmp/tree.data", tree);
return 0;
}
// [--LICENSE--]
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