FMpiFmaLoader.hpp 8.52 KB
Newer Older
1 2
#ifndef FMPIFMALOADER_HPP
#define FMPIFMALOADER_HPP
3
// [--License--]
4 5 6 7 8 9 10 11 12 13 14

#include <iostream>
#include <fstream>

#include "../Utils/FGlobal.hpp"
#include "FAbstractLoader.hpp"
#include "../Utils/F3DPosition.hpp"
#include "../Utils/FMpi.hpp"

/**
* @author Berenger Bramas (berenger.bramas@inria.fr)
15
* @class FMpiFmaLoader
16 17 18 19 20 21 22
* Please read the license
*
* Load a file with a format like :
* NB_particles Box_width Box_X Box_Y Box_Z // init
* X Y Z // one particle by line
* ....
* <code>
23
*    FMpiFmaLoader<FBasicParticle> loader("../FMB++/Tests/particles.basic.txt"); <br>
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
*    if(!loader.isOpen()){ <br>
*        std::cout << "Loader Error\n"; <br>
*        return 1; <br>
*    } <br>
* <br>
*    FOctree<FBasicParticle, TestCell, FSimpleLeaf> tree(loader.getBoxWidth(),loader.getCenterOfBox()); <br>
* <br>
*    for(int idx = 0 ; idx < loader.getNumberOfParticles() ; ++idx){ <br>
*        FBasicParticle* const part = new FBasicParticle(); <br>
*        loader.fillParticle(part); <br>
*        tree.insert(part); <br>
*    } <br>
* </code>
*
* Particle has to extend {FExtendPhysicalValue,FExtendPosition}
*/
template <class ParticleClass>
41
class FMpiFmaLoader : public FAbstractLoader<ParticleClass> {
42 43 44
protected:
    F3DPosition centerOfBox;    //< The center of box read from file
    FReal boxWidth;             //< the box width read from file
45 46
    FSize totalNbParticles;     //< the number of particles read from file
    FSize nbParticles;          //< the number of particles read from file
47 48 49 50 51 52 53 54 55 56
    bool isOpenFlag;            //< to knwo if the file is open now
    FReal* particles;           //< the particles loaded from the binary file
    MPI_Offset idxParticles;    //< to iterate on the particles array

public:
    /**
    * The constructor need the file name
    * @param filename the name of the file to open
    * you can test if file is successfuly open by calling hasNotFinished()
    */
57
    FMpiFmaLoader(const char* const filename, const FMpi::FComm& comm, const bool useMpiIO = false)
58
            : boxWidth(0), totalNbParticles(0), nbParticles(0), isOpenFlag(false), particles(0), idxParticles(0) {
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
        if( useMpiIO ){
            char nonConstFilename[512];
            strcpy(nonConstFilename,filename);
            MPI_File file;
            if(MPI_File_open(MPI::COMM_WORLD, nonConstFilename, MPI::MODE_RDONLY, MPI::INFO_NULL, &file) == MPI_SUCCESS){
                int sizeOfElement(0);
                FReal xyzBoxWidth[4];

                MPI_Status status;
                if( MPI_File_read(file, &sizeOfElement, 1, MPI_INT, &status) == MPI_SUCCESS
                    && MPI_File_read(file, &this->totalNbParticles, 1, MPI_LONG_LONG, &status) == MPI_SUCCESS
                    && MPI_File_read(file, xyzBoxWidth, 4, MPI_FLOAT, &status) == MPI_SUCCESS ){

                    FDEBUG(if(sizeOfElement != sizeof(FReal)){)
                        FDEBUG( FDebug::Controller.writeFromLine("Warning type size between file and FReal are differents\n", __LINE__, __FILE__); )
                    FDEBUG(})

                    this->boxWidth = xyzBoxWidth[3];
                    this->centerOfBox.setPosition(xyzBoxWidth[0],xyzBoxWidth[1],xyzBoxWidth[2]);
                    this->boxWidth *= 2;
                    this->isOpenFlag = true;

                    // load my particles
                    MPI_Offset headDataOffSet(0);
                    MPI_File_get_position(file, &headDataOffSet);

                    MPI_Offset filesize(0);
                    MPI_File_get_size(file, &filesize); // in bytes
                    filesize = (filesize - headDataOffSet) / sizeof(FReal);
                    if(filesize/4 != this->totalNbParticles){
                        printf("Error fileSize %lld, nbPart %lld\n",filesize/4, this->totalNbParticles);
                    }
                    // in number of floats
                    const FSize startPart = comm.getLeft(this->totalNbParticles);
                    const FSize endPart   = comm.getRight(this->totalNbParticles);
                    nbParticles = (endPart - startPart);
                    const FSize bufsize = nbParticles * 4;
                    // local number to read
                    particles = new FReal[bufsize];

                    if( sizeof(FReal) == sizeof(float) ){
                        MPI_File_read_at(file, headDataOffSet + startPart * 4 * sizeof(FReal), particles, int(bufsize), MPI_FLOAT, &status);
                    }
                    else{
                        MPI_File_read_at(file, headDataOffSet + startPart * 4 * sizeof(FReal), particles, int(bufsize), MPI_DOUBLE, &status);
                    }


                    // check if needed
                    int count(0);
                    MPI_Get_count(&status, MPI_INT, &count);
                    FDEBUG(if(count  / 4 != this->nbParticles){)
                        FDEBUG( FDebug::Controller<< "Error read " << count << " data, nbPart is " << this->nbParticles << __LINE__ << " " << __FILE__ << "\n"; )
                    FDEBUG(})
                }
                else{
                    this->totalNbParticles = 0;
                }
                MPI_File_close(&file);
            }
        }
        else {
            FILE* file(fopen(filename, "rb"));
            int removeWarning(0);
            // test if open
            if(file != NULL) {
                int sizeOfElement(0);
                removeWarning += fread(&sizeOfElement, sizeof(int), 1, file);
                FDEBUG(if(sizeOfElement != int(sizeof(FReal)) ){)
128
                    FDEBUG( FDebug::Controller.writeFromLine("Warning type size between file and FReal are differents\n", __LINE__, __FILE__); )
129
                        printf("%d sizeofelement\n",sizeOfElement);
130
                FDEBUG(})
131
                removeWarning += fread(&this->totalNbParticles, sizeof(FSize), 1, file);
132

133
                removeWarning += fread(&this->boxWidth, sizeof(FReal), 1, file);
134
                this->boxWidth *= 2;
135 136 137 138 139 140 141

                FReal x,y,z;
                removeWarning += fread(&x, sizeof(FReal), 1, file);
                removeWarning += fread(&y, sizeof(FReal), 1, file);
                removeWarning += fread(&z, sizeof(FReal), 1, file);
                this->centerOfBox.setPosition(x,y,z);

142 143
                this->isOpenFlag = true;

144 145 146
                const long int headDataOffSet = ftell(file);
                fseek(file, 0L, SEEK_END);
                const long int filesize = (ftell(file) - headDataOffSet) / sizeof(FReal);
147 148

                if(filesize/4 != this->totalNbParticles){
149
                    printf("Error fileSize %ld, nbPart %lld\n", filesize/4, this->totalNbParticles);
150
                }
151

152
                // in number of floats
153 154
                const FSize startPart = comm.getLeft(this->totalNbParticles);
                const FSize endPart   = comm.getRight(this->totalNbParticles);
155
                nbParticles = (endPart - startPart);
156
                const FSize bufsize = nbParticles * 4;
157 158
                // local number to read
                particles = new FReal[bufsize];
159

160
                fseek(file, long(headDataOffSet + startPart * 4 * sizeof(FReal)), SEEK_SET);
161

162
                removeWarning += fread(particles, sizeof(FReal), int(bufsize), file);
163

164
                fclose(file);
165
            }
166 167 168 169 170 171
        }
    }

    /**
    * Default destructor, simply close the file
    */
172
    virtual ~FMpiFmaLoader(){
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
        if(isOpen()){
            delete [] particles;
        }
    }

    /**
      * To know if file is open and ready to read
      * @return true if loader can work
      */
    bool isOpen() const{
        return this->isOpenFlag;
    }

    /**
      * To get the number of particles from this loader
      * @param the number of particles the loader can fill
      */
190
    FSize getNumberOfParticles() const{
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
        return this->nbParticles;
    }

    /**
      * The center of the box from the simulation file opened by the loader
      * @return box center
      */
    F3DPosition getCenterOfBox() const{
        return this->centerOfBox;
    }

    /**
      * The box width from the simulation file opened by the loader
      * @return box width
      */
    FReal getBoxWidth() const{
        return this->boxWidth;
    }

    /**
      * Fill a particle
      * @warning to work with the loader, particles has to expose a setPosition method
      * @param the particle to fill
      */
    void fillParticle(ParticleClass& inParticle){
        inParticle.setPosition(particles[idxParticles],particles[idxParticles+1],particles[idxParticles+2]);
        inParticle.setPhysicalValue(particles[idxParticles+3]);
        idxParticles += 4;
    }

};


224
#endif //FMPIFMALOADER_HPP
225

226
// [--END--]