Commit 098e7285 authored by berenger-bramas's avatar berenger-bramas

Create parallel mpi csv file saver.

git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/scalfmm/scalfmm/trunk@430 2616d619-271b-44dc-8df4-d4a8f33a7222
parent 910dccd6
......@@ -17,15 +17,24 @@ class FTreeMpiCsvSaver {
FMpi::FComm comm; //< Communicator
const bool includeHeader; //< To include a line of header
int nbFrames; //< The current frame
char basefile[512]; //< The base file name like "~/OUT/simulation%d.csv"
char lineFormat[512]; //< The line format
char header[512]; //< The header line
char defaultLine[512]; //< The default line
static const int SizeOfHeader = 8;
static const int SizeOfLine = 56;
public:
/** Constructor
* @param inBasefile is the output file name, you must put %d in it
*/
FTreeMpiCsvSaver(const char inBasefile[], const FMpi::FComm& communicator, const bool inIncludeHeader = false)
: comm(communicator), includeHeader(inIncludeHeader), nbFrames(0) {
: comm(communicator.getComm()), includeHeader(inIncludeHeader), nbFrames(0) {
strcpy(basefile, inBasefile);
strcpy(lineFormat, "%+12.6e,%+12.6e,%+12.6e,%+12.6e\n"); // 56 = 4 x 14 chars
strcpy(header, "x,y,z,v\n"); // 8 chars
}
/** Virtual destructor
......@@ -45,25 +54,95 @@ public:
char currentFilename[512];
sprintf(currentFilename, basefile, nbFrames++);
std::ofstream file(currentFilename, std::ofstream::out );
if(includeHeader){
file << "x, y, z, value\n";
// Erase existing file
if(comm.processId() == 0){
FILE* fd = fopen(currentFilename, "w");
if(fd) fclose(fd);
}
MPI_Barrier(comm.getComm());
// All procs open the file
MPI_File file;
const int fileIsOpen = MPI_File_open( comm.getComm(), currentFilename, MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &file );
// Is it open?
if(fileIsOpen != MPI_SUCCESS){
std::cout << "Cannot create parallel file, exportTree abort." << std::endl;
return;
}
MPI_Offset disp = 0;
{
// Each procs count its particles
int mypart = 0;
typename OctreeClass::Iterator octreeIterator(tree);
octreeIterator.gotoBottomLeft();
do{
mypart += octreeIterator.getCurrentListTargets()->getSize();
const bool isUsingTsm = (octreeIterator.getCurrentListTargets() != octreeIterator.getCurrentListSrc());
if( isUsingTsm ) mypart += octreeIterator.getCurrentListSrc()->getSize();
} while(octreeIterator.moveRight());
// Gather particles number
int*const particlesPerProcs = new int[comm.processCount()];
MPI_Allgather(&mypart, 1, MPI_INT, particlesPerProcs, 1, MPI_INT, comm.getComm());
int previousPart = 0;
for(int idxProc = 0 ; idxProc < comm.processId() ; ++idxProc){
previousPart += particlesPerProcs[idxProc];
}
delete[] particlesPerProcs;
// How many particle before me * size of particle in file
disp = previousPart * SizeOfLine;
if(includeHeader && comm.processId() != 0){
disp += SizeOfHeader;
}
}
// Set view
const char* const native = "native";
MPI_File_set_view( file, disp, MPI_BYTE, MPI_BYTE, const_cast<char*>(native), MPI_INFO_NULL);
// Write header if needed
MPI_Offset offset = 0;
if(includeHeader && comm.processId() == 0){
MPI_File_write_at( file, 0, header, SizeOfHeader, MPI_BYTE, MPI_STATUS_IGNORE);
offset += SizeOfHeader;
}
// Write particle
char line[SizeOfLine+1];
typename OctreeClass::Iterator octreeIterator(tree);
octreeIterator.gotoBottomLeft();
do{
typename ContainerClass::BasicIterator iter(*octreeIterator.getCurrentListTargets());
//const bool isUsingTsm = (octreeIterator.getCurrentListTargets() != octreeIterator.getCurrentListSrc());
while( iter.hasNotFinished() ){
file << iter.data().getPosition().getX() << "," << iter.data().getPosition().getY() << "," <<
iter.data().getPosition().getZ() << "," << getValue(&iter.data()) << "\n";
sprintf(line, lineFormat, iter.data().getPosition().getX(),iter.data().getPosition().getY(),
iter.data().getPosition().getZ(),getValue(&iter.data()));
MPI_File_write_at( file, offset, line, SizeOfLine, MPI_BYTE, MPI_STATUS_IGNORE);
offset += SizeOfLine;
iter.gotoNext();
}
const bool isUsingTsm = (octreeIterator.getCurrentListTargets() != octreeIterator.getCurrentListSrc());
if( isUsingTsm ){
typename ContainerClass::BasicIterator iterSource(*octreeIterator.getCurrentListSrc());
while( iterSource.hasNotFinished() ){
sprintf(line, lineFormat, iterSource.data().getPosition().getX(),iterSource.data().getPosition().getY(),
iterSource.data().getPosition().getZ(),getValue(&iterSource.data()));
MPI_File_write_at( file, offset, line, SizeOfLine, MPI_BYTE, MPI_STATUS_IGNORE);
offset += SizeOfLine;
iterSource.gotoNext();
}
}
} while(octreeIterator.moveRight());
file.close();
MPI_File_close( &file );
}
/** Inherit from this class and customize this function if you need it
......
// ===================================================================================
// Logiciel initial: ScalFmm Version 0.5
// Co-auteurs : Olivier Coulaud, Bérenger Bramas.
// Propriétaires : INRIA.
// Copyright © 2011-2012, diffusé sous les termes et conditions d’une licence propriétaire.
// Initial software: ScalFmm Version 0.5
// Co-authors: Olivier Coulaud, Bérenger Bramas.
// Owners: INRIA.
// Copyright © 2011-2012, spread under the terms and conditions of a proprietary license.
// ===================================================================================
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include "../Src/Utils/FTic.hpp"
#include "../Src/Utils/FParameters.hpp"
#include "../Src/Utils/FMpi.hpp"
#include "../Src/Containers/FOctree.hpp"
#include "../Src/Containers/FVector.hpp"
#include "../Src/Extensions/FExtendVelocity.hpp"
#include "../Src/Files/FTreeMpiCsvSaver.hpp"
#include "../Src/Files/FFmaLoader.hpp"
#include "../Src/Arranger/FOctreeArranger.hpp"
#include "../Src/Components/FSimpleLeaf.hpp"
#include "../Src/Components/FBasicCell.hpp"
#include "../Src/Kernels/FSphericalParticle.hpp"
class FmmVeloParticle : public FSphericalParticle, public FExtendVelocity {
};
template <class ParticleClass>
class GalaxyLoader : public FFmaLoader<ParticleClass> {
public:
GalaxyLoader(const char* const filename) : FFmaLoader<ParticleClass>(filename) {
}
void fillParticle(ParticleClass& inParticle){
FReal x,y,z,data, vx, vy, vz;
this->file >> x >> y >> z >> data >> vx >> vy >> vz;
inParticle.setPosition(x,y,z);
inParticle.setPhysicalValue(data);
inParticle.setVelocity(vx,vy,vz);
inParticle.setPhysicalValue(FReal(0.10));
}
};
template <class OctreeClass, class ContainerClass , class ParticleClass>
class MassSaver : public FTreeMpiCsvSaver<OctreeClass,ContainerClass, ParticleClass> {
public:
MassSaver(const char inBasefile[], const FMpi::FComm& inComm, const bool inIncludeHeader = false)
: FTreeMpiCsvSaver<OctreeClass,ContainerClass, ParticleClass>(inBasefile, inComm, inIncludeHeader) {
}
virtual FReal getValue(ParticleClass*const part){
return part->getPhysicalValue();
}
};
// Simply create particles and try the kernels
int main(int argc, char ** argv){
typedef FmmVeloParticle ParticleClass;
typedef FBasicCell 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 test Spherical algorithm.\n";
//////////////////////////////////////////////////////////////
FMpi app( argc, argv);
const int NbLevels = FParameters::getValue(argc,argv,"-h", 6);
const int SizeSubLevels = FParameters::getValue(argc,argv,"-sh", 3);
GalaxyLoader<ParticleClass> loader(FParameters::getStr(argc,argv,"-f", "../Data/galaxy.fma.tmp"));
// -----------------------------------------------------
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;
{
ParticleClass particleToFill;
for(int idxPart = 0 ; idxPart < loader.getNumberOfParticles() ; ++idxPart){
loader.fillParticle(particleToFill);
if( (idxPart+1) % (app.global().processId()+1) == 0) tree.insert(particleToFill);
}
}
// -----------------------------------------------------
{
MassSaver<OctreeClass, ContainerClass, ParticleClass> saver("./out/test%d.csv", app.global() , false);
saver.exportTree(&tree);
}
// -----------------------------------------------------
{
MassSaver<OctreeClass, ContainerClass, ParticleClass> saver("./out/htest%d.csv", app.global() , true);
saver.exportTree(&tree);
}
return 0;
}
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